我是Haskell的初学者(ish),我发现错误信息真的很难理解(我想它随着时间的推移而来).无论如何,为了帮助我理解我的错误,我尝试在let绑定中添加带有类型注释的中间变量,并发现它产生更多错误,即使我的类型(我认为)正确.
例;
f :: a -> a
f x =
let x' = x :: a
in x'
Run Code Online (Sandbox Code Playgroud)
生成以下错误
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
Run Code Online (Sandbox Code Playgroud)
我做错了什么或者不可能这样做?
kos*_*kus 30
你需要ScopedTypeVariables扩展才能工作,如下所示:
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. a -> a
f x =
let x' = x :: a
in x'
Run Code Online (Sandbox Code Playgroud)
如果你有这样的类型签名
f :: a -> a
Run Code Online (Sandbox Code Playgroud)
然后它表明它f是多态的,适用于任何选择a.所以f可以在类型Int -> Int,类型Bool -> Bool或类型中使用[Int -> Bool] -> [Int -> Bool]- 无论你喜欢什么.
如果你有这样的类型注释
x :: a
Run Code Online (Sandbox Code Playgroud)
它意味着类似的东西,即x应该可以用于您选择的任何类型.但在你的情况下,情况并非如此.外部函数f是多态的,但在函数内,x必须与用户为外部选择的类型相同.默认情况下,Haskell不会在不同类型签名和注释中出现的类型变量之间建立连接.但是,您可以通过启用扩展程序来告知它这样做.现在,前缀用,你可以明确地指示哈斯克尔作出可见的定义范围内的特定类型的变量.如果你然后注释,它指的是外部而不是新的多态.axScopedTypeVariablesa -> aforall a.afx :: aaa
对于任何想要键入注释而不是表达式的人来说 - ScopedTypeVariables允许你也这样做!
f1 = do
let x :: Int = 5
y :: Int <- someMonadicOperation
return $ x + y
Run Code Online (Sandbox Code Playgroud)