Haskell 如何在let绑定中添加类型注释
我是Haskell的初学者,我发现错误消息很难理解(我想它是随时间而来的)。无论如何,为了帮助我理解我的错误,我尝试在let绑定中添加带有类型注释的中间变量,发现它会生成更多错误,即使我的类型(我认为)是正确的 榜样Haskell 如何在let绑定中添加类型注释,haskell,Haskell,我是Haskell的初学者,我发现错误消息很难理解(我想它是随时间而来的)。无论如何,为了帮助我理解我的错误,我尝试在let绑定中添加带有类型注释的中间变量,发现它会生成更多错误,即使我的类型(我认为)是正确的 榜样 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
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
我做错了什么事还是不可能做?这应该可以:
f :: s -> s
f x =
let y = undefined :: s
in y
只需使用上面示例中所示的普通:
运算符进行类型注释
更新:
它似乎不适用于多态类型。但它适用于混凝土类型
以下类型检查:
f :: Int -> Int
f x = let m = x :: Int
in m
这会产生错误:
f1 :: a -> a
f1 x = let m = x :: a
in m
解决方案
您需要ScopedTypeVariables
扩展才能使其工作,如下所示:
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. a -> a
f x =
let x' = x :: a
in x'
解释
如果你有这样的类型签名
f :: a -> a
x :: a
然后它表示f
是多态的,并且适用于a
的任何选择。所以f
可能是
用于类型Int->Int
,或类型Bool->Bool
,或类型[Int->Bool]->[Int->Bool]
——随你喜欢
如果您有这样的类型注释
f :: a -> a
x :: a
这意味着类似的事情,即
x
应该可以在您选择的任何类型上使用。但你的情况并非如此。外部函数f
是多态的,但在该函数中,x
必须与用户为外部x
选择的a
类型相同。默认情况下,Haskell不会在不同类型签名和注释中出现的类型变量之间建立连接。但是,您可以通过启用ScopedTypeVariables
扩展来告诉它这样做。现在,通过在a->a
前面加上作为所有a.
的前缀,您可以明确指示Haskell使a
作为f
定义中的特定类型变量可见。如果您随后注释x::a
,它指的是外部a
,而不是一个新的多态a
,对于任何希望为绑定而不是表达式进行类型注释的人来说-ScopedTypeVariables
也允许您这样做
f1 = do
let x :: Int = 5
y :: Int <- someMonadicOperation
return $ x + y
f1=do
设x::Int=5
你说的“你还没有定义函数本身”是什么意思?如果我删除类型注释,该函数将得到很好的定义和运行。第三个示例基本上是我的问题,它为什么不工作?抱歉,它不适用于多态类型。使用komiskus解释的ScopedTypeVariables
扩展。我假设您正确地编写了fx=…
,而不是let fx=…
哇,我已经找了很久了!