Haskell功能依赖冲突

为什么会导致冲突?
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'

因为两个实例都满足,因此重叠.

很开心啊

相关文章

适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题...
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结...
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容...