单态限制对类型约束的影响

此代码在添加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的类型算法有一些其他机制可以消除歧义。

链接地址: http://www.djcxy.com/p/43123.html

上一篇: Effects of monomorphism restriction on type class constraints

下一篇: Web service to get the GPS Coordinates