我曾经试着谷歌搜索,但是没有找到相关信息。我正在通过阅读一些文章来进一步学习Haskell知识,然后我遇到了一个使用我从未见过语法的例子。
reconstruct node@(Node a b c l r) parent@(Node b d le ri)
我以前从未见过这些@符号。我尝试在网上搜索答案,但没有找到。这只是一种嵌入标签以帮助使事情更清晰的方法,还是它们对代码有实际影响?
我曾经试着谷歌搜索,但是没有找到相关信息。我正在通过阅读一些文章来进一步学习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
看看第一个版本是多么简单?
someFunction leaf@Leaf{} = leaf
。 - András KovácsLeaf{}
进行一些解释吗? - d12frosted{-# LANGUAGE TypeApplications #-}
,不过还在学习它是什么。 - Josh.Ffoo @Int
很容易是一个函数,它接受两个字符并生成一个返回 ()
的 IO
操作。 - dfeuer除了 @Sibi 的答案中描述的参数模式匹配用法之外,在 Haskell 中,“at”字符('@',也称为 艾特符号)可以在某些情况下用于强制类型决策。这是由 @Josh.F. 在评论中提到的。
这不是默认语言功能的一部分,而是已知的类型应用 Haskell 语言扩展。简而言之,该扩展允许您向多态函数(如 read
)提供显式类型参数。在经典的 .hs 源文件中,相关的 pragma 必须被包含:
{-# 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
在这里,我们有三个类型变量,按出现顺序为: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
返回的结果类型相关,如上所示。