简体   繁体   English

单同性约束对类型约束的影响

[英]Effects of monomorphism restriction on type class constraints

This code breaks when a type declaration for baz is added: 添加baz的类型声明时,此代码会中断:

baz (x:y:_) = x == y
baz [_] = baz []
baz [] = False

A common explanation (see Why can't I declare the inferred type? for an example) is that it's because of polymorphic recursion. 一个常见的解释(请参阅为什么我不能声明推断类型?例如)是因为多态递归。

But that explanation doesn't explain why the effect disappears with another polymorphically recursive example: 但是这个解释并没有解释为什么效果会随着另一个多态递归示例而消失:

foo f (x:y:_) = f x y
foo f [_] = foo f []
foo f [] = False

It also doesn't explain why GHC thinks the recursion is monomorphic without type declaration. 它也没有解释为什么GHC认为在没有类型声明的情况下递归是单态的。

Can the explanation of the example with reads in http://www.haskell.org/onlinereport/decls.html#sect4.5.5 be applied to my baz case? 可以将对http://www.haskell.org/onlinereport/decls.html#sect4.5.5中的 reads示例的解释应用于我的baz案例吗?

Ie adding a signature removes monomorphism restriction, and without the restriction an ambiguity of right-side [] appears, with an 'inherently ambigous' type of forall a . Eq a => [a] 即添加签名会消除单态限制,并且没有限制,右侧[]的模糊性出现,具有“固有的暧昧”类型的forall a . Eq a => [a] forall a . Eq a => [a] ? forall a . Eq a => [a]

The equations for baz are in one binding group, generalisation is done after the entire group has been typed. baz的方程在一个绑定组中,在整个组被输入后进行泛化。 Without a type signature, that means baz is assumed to have a monotype, so the type of [] in the recursive call is given by that (look at ghc's -ddump-simpl output). 没有类型签名,这意味着baz被假定为具有单型,因此递归调用中的[]类型由此给出(查看ghc的-ddump-simpl输出)。 With a type signature, the compiler is explicitly told that the function is polymorphic, so it can't assume the type of [] in the recursive call to be the same, hence it's ambiguous. 使用类型签名,编译器被明确告知该函数是多态的,因此它不能假定递归调用中[]的类型是相同的,因此它是不明确的。

As John L said, in foo , the type is fixed by the occurrence of f - as long as f has a monotype. 正如John L所说,在foo ,只要f具有一个单型, f的出现就会固定类型。 You can create the same ambiguity by giving f the same type as (==) (which requires Rank2Types ), 您可以通过赋予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

That gives 这给了

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 []

Your second example isn't polymorphically recursive. 你的第二个例子不是多态递归的。 This is because the function f appears on both the LHS and RHS of the recursive definition. 这是因为函数f出现在递归定义的LHS和RHS上。 Also consider the type of foo , (a -> a -> Bool) -> [a] -> Bool . 还要考虑foo的类型, (a -> a -> Bool) -> [a] -> Bool This fixes the list element type to be identical to the type of f 's arguments. 这将列表元素类型修复为与f的参数类型相同。 As a result, GHC can determine that the empty list on the RHS must have the same type as the input list. 因此,GHC可以确定RHS上的空列表必须与输入列表具有相同的类型。

I don't think that the reads example is applicable to the baz case, because GHC is able to compile baz with no type signature and the monomorphism restriction disabled. 我不认为reads示例适用于baz情况,因为GHC能够编译没有类型签名的baz并禁用单态限制。 Therefore I expect that GHC's type algorithm has some other mechanism by which it removes the ambiguity. 因此,我希望GHC的类型算法有一些其他机制可以消除歧义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM