单态限制对类型约束的影响
此代码在添加baz
的类型声明时中断:
baz (x:y:_) = x == y
baz [_] = baz []
baz [] = False
一个常见的解释(请参阅为什么我不能声明推断的类型?例如)是因为多态递归。
但是这个解释并不能解释为什么这个效应会以另一个多态递归的例子消失:
foo f (x:y:_) = f x y
foo f [_] = foo f []
foo f [] = False
它也不能解释为什么GHC认为递归没有类型声明是单形的。
与示例的解释可以reads
在http://www.haskell.org/onlinereport/decls.html#sect4.5.5被应用到我的baz
情况?
即添加一个签名可以消除单态限制,并且在没有限制的情况下,出现右侧[]的模糊性,同时出现一个“固有含糊”的类型forall a . Eq a => [a]
forall a . Eq a => [a]
?
baz
的公式在一个绑定组中,泛化在整个组被输入后完成。 如果没有类型签名,这意味着baz
被认为具有monotype,所以递归调用中的[]
类型由该类型给出(查看ghc的-ddump-simpl输出)。 使用类型签名时,编译器会明确告知函数是多态的,所以它不能假定递归调用中的[]
类型是相同的,因此它是不明确的。
正如约翰L所说的,在foo
,类型是由f
的发生所固定 - 只要f
具有单型。 您可以通过给创建相同的歧义f
同一类型(==)
要求Rank2Types
)
{-# LANGUAGE Rank2Types #-}
foo :: Eq b => (forall a. Eq a => a -> a -> Bool) -> [b] -> Bool
foo f (x:y:_) = f x y
foo f[_] = foo f []
foo _ [] = False
这给了
Ambiguous type variable `b0' in the constraint:
(Eq b0) arising from a use of `foo'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: foo f []
In an equation for `foo': foo f [_] = foo f []
你的第二个例子不是多态递归。 这是因为函数f
出现在递归定义的LHS和RHS上。 还要考虑foo
的类型, (a -> a -> Bool) -> [a] -> Bool
。 这将列表元素类型修复为与f
的参数类型相同。 因此,GHC可以确定RHS上的空列表必须与输入列表具有相同的类型。
我不认为reads
示例适用于baz
情况,因为GHC能够编译没有类型签名的baz
,并禁用单态禁止。 因此,我期望GHC的类型算法有一些其他机制可以消除歧义。
上一篇: Effects of monomorphism restriction on type class constraints