在Haskell中,为什么要定义具有类型约束的函数:
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
而不是定义它所以它的类型是:
ghci> :t (==)
(==) :: Eq -> Eq -> Bool
答案 0 :(得分:8)
你不会做第二个版本,因为你会遇到编译错误。 Eq
不是类型,它是类型类。您不能在需要类型的地方使用类型类。
如果您确定了自己的类型MyEq
,然后定义了类型为==
的函数MyEq -> MyEq -> Bool
,则表达式"hello" == "hello"
将无效,因为"hello"
是String类型的值,而不是MyEq类型的值。由于haskell中没有子类型,因此值不能同时为String类型和MyEq类型。
因此,如果要定义一个可以接受满足特定条件的不同类型值的函数,则需要输入类型。
答案 1 :(得分:7)
在Haskell中,“类型”只能有一组特定的可能值 不与任何其他类型重叠。 没有一种类型是“不同类型”的东西 或“另一种类型的子类型。”
当我们想要多态时,即可以应用于多个的函数 一种类型,我们可以通过在类型中使用类型变量来指定 功能的签名。
但是类型变量可以引用任何
完全打字。我们并不总是知道如何定义我们的功能
绝对适合所有类型。例如,(>)
函数仅对其元素类型有意义
可比。编译器会拒绝
类型签名过于笼统的函数
帮助我们避免写胡言乱语。
在您的示例中,Eq
不是类型。它是一个
类型类 - 一组类型的名称。我们宣布
使用class
关键字的类型名称和
使用instance
将类型添加到类中
关键词。类型类的目的是在a中使用
约束限制
类型变量的范围。
Haskell对类型和多态的方法是基于 “Hindley-Milner型系统”。这是非常精确的 但是非常富有表现力的描述数据的方式 更容易给编译器提供大量的智能 关于程序中的类型。这种情报有助于 编译器自动推断类型,给你 在帮助您的程序正确和优化方面提供了很多帮助 汇总结果以及其他好处。
但要小心 - 它与类型的方式非常不同 在OOP中使用,这可能是你习惯的。通常没有 OO程序和Haskell程序之间的直接转换。 你必须以不同的方式考虑这项任务 开始。要特别注意不要混淆Haskell的概念 “阶级”和“实例”与那些完全不同的方式 OOP中使用了单词。