这是一个哲学问题,但我希望能够通过官方文档或“神的话语”(即SPJ)得到答案。Haskell委员会是否有特定原因选择要求使用类型类形式的显式接口,而不是基于模式匹配的更统一的解决方案?以
为什么我们不能像这样做(请忍受伪Haskell):
也就是说,如果Haskell允许对普通数据类型进行模式匹配,则:
Eq
为例:class Eq a where
(==), (/=) :: a -> a -> Bool
x == y = not $ x /= y
x /= y = not $ x == y
instance Eq Int where
(==) = internalIntEq
为什么我们不能像这样做(请忍受伪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
也就是说,如果Haskell允许对普通数据类型进行模式匹配,则:
程序员可以创建特定的类,即
instance
将是隐式的 (2)类型仍然可以被静态地推断和匹配 (
SupportsEqualsEquals a => ...
)默认实现将会“自动”生成
类可以轻松扩展而不会破坏任何东西
需要有一种方法来指定一个默认模式(1),尽管在其他模式声明之前,但总是最后匹配。这些假设功能中是否有任何与Haskell固有特性相冲突的内容?推断类型会变得困难或不可能吗?看起来这是一个非常强大的功能,很好地与Haskell的其余部分结合,因此我认为我们没有采用这种方式的充分理由。这种特定的多态机制是否过于特定了?
id :: a -> a
或者fst :: (a,b) -> a
的作用,因为它们只有参数多态性。如果你有某种类型情况机制,那么你就会失去参数性。例如,a -> a -> Bool
在 Haskell 中只有两个(总)实现方式(const $ const True
和const $ const False
);如果你有类型情况,那么你就会失去这个保证。 - Antal Spector-Zabuskyid :: a -> a
,然后定义id (Int i) = i + 1
吗?因为这不是事实:后面的定义将是类型SupportsPlus a => a -> a
,与之不兼容。 - Jon Purdy(==)
的类型签名为a -> a -> Bool
。如果你必须指定一个“类型类”SupportsEquals
,那么看起来你只是在交换语法 - 我不明白为什么它会不同。我认为它不能表达多参数类型类、函数依赖或关联类型,尽管这些当然不在最初的计划中。实际上,它甚至能否表达更高维度的类型类?你如何知道return :: a -> m a
应该针对于m
而不是a
进行特别处理? - Antal Spector-Zabuskyi
明显是一个Int
,它是如何被推导为SupportsPlus a => a
的?同样的泛化规则,无论是什么,是否适用于所有定义或仅适用于使用 typecase 符号的定义?这是否意味着,即使没有全局的id :: a -> a
签名,id (Int i) = i + 1
的类型也是SupportsPlus a => a -> a"
?如果是这样,像id 3.7
这样的表达式的语义是什么? - Doug McClean