Haskell 中的“@”是什么意思?

What does '@' mean in Haskell?

我试过谷歌搜索,但没有找到答案。我通过阅读一些文章来进一步扩展我的 Haskell 知识,并且我遇到了一篇使用我以前从未见过的语法的文章。 一个例子是:

reconstruct node@(Node a b c l r) parent@(Node b d le ri)

我以前从未见过这些@。我试着在网上搜索答案,但没有找到答案。这仅仅是一种嵌入标记以帮助使事情更清晰的方法,还是它们对代码有实际影响?

用于模式匹配。现在 node 变量将引用参数 Node a b c l r 的整个 Node 数据类型。因此,您可以使用 node 而不是将其作为 Node a b c l r 传递给函数。

一个更简单的例子来演示它:

data SomeType = Leaf Int Int Int | Nil deriving Show

someFunction :: SomeType -> SomeType
someFunction leaf@(Leaf _ _ _) = leaf
someFunction Nil = Leaf 0 0 0

someFunction也可以写成:

someFunction :: SomeType -> SomeType
someFunction (Leaf x y z) = Leaf x y z
someFunction Nil = Leaf 0 0 0

看看第一个版本有多简单?

使用@t 作为类型指示符

除了@Sibi 的回答中描述的参数模式匹配用法外,在Haskell中可以使用“at”字符('@',也称为arobase字符)某些上下文强制输入决定。 @Josh.F.

的评论中提到了这一点

不是 默认语言功能的一部分,被称为 Type Application Haskell 语言扩展。总之,该扩展允许您为多态函数提供显式类型参数,例如 read。在经典的 .hs 源文件中,必须包含相关的编译指示:

{-#  LANGUAGE TypeApplications  #-}

示例:

$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/  :? for help
 λ> 
 λ> let x = (read @Integer "33")

 <interactive>:4:10: error:
    Pattern syntax in expression context: read@Integer
    Did you mean to enable TypeApplications?
 λ> 
 λ> :set -XTypeApplications
 λ>
 λ> let x = (read @Integer "33")
 λ>
 λ> :type  x
 x :: Integer
 λ> 
 λ> x
 33
 λ> 

更多详情

对于read多态函数,@引入的类型指示符与read返回结果的类型有关。但这通常是

一般来说,您必须考虑手头函数的类型签名中出现的类型变量。例如,让我们看一下 fmap 库函数。

fmap :: Functor ft => (a -> b) -> ft a -> ft b

所以在这里,我们有 3 个类型变量,按出现顺序排列:ft、a、b。如果我们这样特化 fmap

myFmap = fmap  @type1  @type2  @type3

那么 type1 将与 ft 相关,type2 将与 a 相关,而 type3 将与 b 相关。此外,还有一个特殊的虚拟类型指示器 @_,意思是:“这里,任何类型都可以 ”。

例如,我们可以强制 fmap 的输出类型为 Integer,函子为普通列表 [],而输入类型为 a未指定:

 λ> 
 λ> myFmap = fmap  @[]  @_  @Integer
 λ> 
 λ> :type myFmap
 myFmap :: (_ -> Integer) -> [_] -> [Integer]
 λ> 

至于read函数,它的类型是:

read :: Read a => String -> a

所以只有一种类型指标有空间,它与read返回结果的类型有关,如上所示。