【发布时间】:2013-02-06 09:58:31
【问题描述】:
假设我要在字符串上定义(+),而不是通过给出Num String 的实例。
为什么 Haskell 现在隐藏了 Nums (+) 函数?毕竟我提供的功能:
(+) :: String -> String -> String
可以通过编译器与 Prelude 的(+) 区分开来。为什么两个函数不能存在于同一个命名空间中,但具有不同的、不重叠的类型签名?
只要代码中没有调用函数,Haskell 就会关心是否存在歧义。然后使用参数调用函数将确定类型,以便选择适当的实现。
当然,一旦有实例Num String,实际上就会发生冲突,因为此时Haskell无法根据参数类型决定选择哪个实现,如果函数被实际调用。
在这种情况下,应该引发错误。
这不允许函数重载而没有陷阱/歧义吗?
注意:我不是在谈论动态绑定。
【问题讨论】:
-
正如其他人所说,Haskell 仅通过类型类提供重载。这不是设计语言的唯一方法,但它有一个很好的属性,您可以实际为程序片段赋予类型,例如,
(+)具有类型(Num a) => a -> a -> a。有了你的建议,(+)就没有任何类型了。 -
那么这将不是一个 Hindley-Milner 类型系统。类型推断会更复杂。
(+)的类型必须是真正的联合,"''true union'' types are not present in Haskell"。如果允许,一些拼写错误将被接受为类型良好的程序。 tagged union types 没有歧义(即当我们明确地是 forced to use type constructors 时)。 -
@WillNess 是否有充分的理由说明“Hindley-Milner 类型系统”应该比他提出的更好?它有什么优点?该提案的缺点是什么?
-
@Odin 也许它的类型推断算法更简单。
标签: haskell types language-design