为什么会导致冲突?
class Foo a b | b -> a where foo :: a -> b -> Bool instance Eq a => Foo a a where foo = (==) instance Eq a => Foo a (a -> a) where foo x f = f x == x
我的印象是,功能依赖只应该禁止像以下这样的东西,实际上它会编译!
class Foo a b | b -> a where foo :: a -> b -> Bool instance Eq a => Foo a a where foo = (==) instance Eq a => Foo Bool a where foo _ x = x == x
相同的b参数,但参数不同.不应该b – >不允许这个,因为这意味着一个由b唯一确定?
你是否尝试使用第二个版本?我猜测,当实例编译时,当您调用foo时,您将开始变得模糊和重叠错误.
这里最大的障碍是,屁股不会像您可能期望的那样与类型变量进行交互 – 实例选择并不真正寻找解决方案,它只是通过尝试统一而盲目匹配.具体来说,当你写Foo a a时,a是完全任意的,因此可以使用类似b – >湾当第二个参数的形式为b – > b,它因此匹配两个实例,但是基数表示在一种情况下,第一个参数应该是b – > b,但另一方面应该是b.所以冲突.
由于这显然令人惊讶,所以如果您尝试使用第二个版本,会发生什么:
> bar = foo()()导致:
Couldn't match type `Bool' with `()' When using functional dependencies to combine Foo Bool a,
…因为基金会通过第二个例子说,任何类型作为第二个参数唯一地将Bool确定为第一个.所以第一个参数必须是Bool.
> bar = foo True()导致:
Couldn't match type `()' with `Bool' When using functional dependencies to combine Foo a a,
…因为基金会说,通过第一个实例,任何类型作为第二个参数唯一地确定了第一个参数的相同类型.所以第一个参数必须是().
> bar = foo()由于这两个实例,True都导致错误,因为这次他们同意第一个参数应该是Bool.
> bar = foo True True产生于:
Overlapping instances for Foo Bool Bool arising from a use of `foo'
因为两个实例都满足,因此重叠.
很开心啊