pok*_*oke 19 haskell types scope type-mismatch
我对Haskell的where
定义范围有疑问.当我有以下函数f
,我希望将其传递x
给本地定义的函数f1
而不明确地将其用作参数时,我得到一个错误,说明类型x
与输出中的类型不兼容f1
,尽管它应该是相同:
f :: Eq a => a -> [a] f x = f1 x where f1 :: Eq a => a -> [a] f1 y = [ x, y ]
错误如下:
Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `f1' at test.hs:4:11 `a' is a rigid type variable bound by the type signature for `f' at test.hs:1:8 In the expression: x In the expression: [x, y] In the definition of `f1': f1 y = [x, y] Failed, modules loaded: none.
然而,当我传递x
作为附加参数时,正如我在下面的代码中使用该函数所做的那样g
,它工作正常:
g :: Eq a => a -> [a] g x = g1 x x where g1 :: Eq a => a -> a -> [a] g1 x y = [ x, y ]
有没有一种方法,使类型a
中f
的类型兼容a
(或a1
)的f1
?
Dan*_*Dan 18
戴夫就在上方.另一种思考方式是即使你的两个类型签名都引用变量a
,它实际上并不是同一个类型变量.在Haskell-prime表示法中,两个签名都可以更明确地写为:
forall a . Eq a => a -> [a]
意思是对于这两个函数,它们可以接受任何类型的参数(在Eq中).这显然不是这里的情况.在标准的Haskell 98中,唯一的选择是放弃类型签名f1
.但是GHC(和其他人?)支持词法范围的类型变量.所以你可以写
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. Eq a => a -> [a]
f x = f1 x
where
f1 :: a -> [a]
f1 y = [ x, y ]
Run Code Online (Sandbox Code Playgroud)
那会很好.
Dav*_*ave 11
您的代码的问题是本地范围的f1类型签名.它指定f1可以采用任何类型
f1 :: Eq a => a -> [a]
即使这是一个本地函数,你已经推广了这个函数,以便能够获取f中不存在的类型,无论此函数接收来自f的HAS,因此类型签名是不必要的.
只需删除f1类型签名即可.
编辑:回复自己的帖子,有点不清楚.f1中的a是一个参数化类型,可以取任何东西,但传递给它的参数已经绑定在f中.因此,此函数只能接收其父函数接收的内容,您给它的类型签名会破坏该规则.希望更清楚一点.