我是 Haskell 的初学者,我发现错误消息真的很难理解(我想它会随着时间的推移而出现)。不管怎样,为了帮助我理解我的错误,我尝试在 let 绑定(bind)中添加带有类型注释的中间变量,发现它会生成更多错误,即使我的类型(我认为)是正确的。
示例;
f :: a -> a
f x =
let x' = x :: a
in x'
产生以下错误
test.hs:3:12:
Couldn't match expected type `a2' with actual type `a'
`a2' is a rigid type variable bound by
an expression type signature: a2 at test.hs:3:12
`a' is a rigid type variable bound by
the type signature for f :: a -> a at test.hs:1:6
In the expression: x :: a
In an equation for x': x' = x :: a
In the expression: let x' = x :: a in x
我做错了什么还是不可能这样做?
最佳答案
解决方案
您需要 ScopedTypeVariables
扩展才能使其工作,如下所示:
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. a -> a
f x =
let x' = x :: a
in x'
说明
如果你有这样的类型签名
f :: a -> a
那么它表明f
是多态的并且适用于a
的任何选择。所以 f
可能是
用于 Int -> Int
类型,或 Bool -> Bool
类型,或 [Int -> Bool] -> [Int -> Bool] 类型
– 无论你喜欢什么。
如果你有这样的类型注释
x :: a
这意味着类似的事情,即 x
应该可用于您选择的任何类型。但你的情况并非如此。外部函数 f
是多态的,但在函数内部,x
必须具有与a
相同的类型用户已选择外部x
。默认情况下,Haskell 不会在不同类型签名和注释中出现的类型变量之间建立任何联系。但是,您可以通过启用 ScopedTypeVariables 扩展来告诉它这样做。现在,通过在 a -> a
前面添加 forall a.
,您可以显式指示 Haskell 将 a
作为特定类型变量在f
的定义。如果您随后注释 x::a
,它会引用外部 a
,而不是新的多态 a
。
关于haskell - 如何在let绑定(bind)中添加类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22436402/