为什么类型类而不仅仅是模式匹配?

Jon*_*rdy 7 haskell pattern-matching typeclass

这是一个哲学问题,但我希望通过官方文件或"上帝之词"(读作:SPJ)来回答这个问题.是否有一个特定的原因,Haskell委员会选择以类型的形式要求显式接口而不是基于模式匹配的更统一的解决方案?

例如,采取Eq:

class Eq a where
    (==), (/=) :: a -> a -> Bool
    x == y = not $ x /= y
    x /= y = not $ x == y

instance Eq Int where
    (==) = internalIntEq
Run Code Online (Sandbox Code Playgroud)

为什么我们不能做这样的事情(承担伪Haskell):

(==), (/=) :: a -> a -> Bool
default x == y = not $ x /= y             -- 1
default x /= y = not $ x == y

(Int a) == (Int b) = a `internalIntEq` b  -- 2
Run Code Online (Sandbox Code Playgroud)

也就是说,如果Haskell允许普通数据类型的模式匹配,那么:

  • 程序员可以创建ad-hoc类,即instance隐式(2)

  • 类型仍然可以推断和静态匹配(SupportsEqualsEquals a => ...)

  • 默认实现将"免费"

  • 可以很容易地扩展课程而不会破坏任何东西

需要有一种方法来指定默认模式(1),虽然在其他模式之前声明,但始终与最后匹配.这些假设特征中的任何一个都与Haskell中固有的东西相冲突吗?正确推断类型会变得困难或不可能吗?这似乎是一个强大的功能,与Haskell的其余部分很好地凝聚,所以我认为有一个很好的理由我们不做那样的方式™.ad-hoc多态的这种机制是否过于特殊?

Dan*_*ton 12

ad-hoc多态的这种机制是否过于特殊?

这个问题只是与Philip Wadler和Steve Blott的1988年论文" 如何使ad-hoc多态性不那么临时"联系起来,他们提出了Type类的概念.Wadler可能就此而言是"上帝的话语".

我在建议的"任何Haskell数据类型的模式匹配"技术中看到了一些问题.

模式匹配技术不足以定义多态常量,例如mempty :: Monoid a => a.

除了更糟糕的方式之外,模式匹配技术仍然会回归到类型类别.类型类对类型进行分类(参见图).但模式匹配技术使其相当模糊.你究竟应该如何指定这些函数foo并且bar是"同一"类的一部分?如果你必须为你使用的每个单态多态函数添加一个新类型,那么类型类约束将变得完全不可读.

模式匹配技术将新语法引入Haskell,使语言规范复杂化.该default关键字看起来不那么糟糕,但模式匹配"的类型"是新的,令人困惑.

"普通数据类型"模式匹配失败了无点样式.而不是(==) = intEq,我们有(Int a) == (Int b) = intEq a b; 这种人工模式匹配可防止eta减少.

最后,它完全改变了我们对类型签名的理解. a -> a -> Foo目前保证无法检查输入.a除了两个输入是相同类型之外,没有任何关于输入的假设.[a] -> [a]再次意味着列表中的元素无法以任何有意义的方式进行检查,为您提供免费定理(另一个Wadler论文).

可能有一些方法可以解决这些问题,但我的总体印象是Type类已经以优雅的方式解决了这个问题,并且建议的模式匹配技术不会带来任何好处,同时会导致一些问题.