我是Haskell的新手,一般来说,是函数式编程,我对它的语法有点不舒服。
在以下代码中=>
表示什么?还有(Num a, Ord a)
?
loop :: (Num a, Ord a) => a -> (t -> t) -> t -> t
答案 0 :(得分:34)
这是一个类型类约束; (Num a, Ord a) => ...
表示loop
适用于任何类型a
,它是Num
和Ord
类型类的实例,分别对应于数字类型和有序类型。基本上,您可以将loop
视为=>
右侧的类型,但a
必须是Num
和{{Ord
的实例。 1}}。
你可以认为类型类似于OOP接口(但它们不是同一个东西!) - 它们封装了一组任何实例必须支持的定义,并且可以使用这些定义编写通用代码。例如,Num
包括数字操作,如加法和乘法,而Ord
包括小于,大于等等。
有关类型类的详细信息,请参阅this introduction中的Learn You a Haskell。
答案 1 :(得分:16)
=>
分隔出类型签名的两个部分:
因此,您可以将(Num a, Ord a) => a -> (t -> t) -> t -> t
视为“类型为a -> (t -> t) -> t -> t
,并且Num
和a
实例必须有Ord
个实例对于a
“。
有关类型类的更多信息,请参阅http://www.learnyouahaskell.com/types-and-typeclasses
答案 2 :(得分:5)
考虑它的一种方法是Ord a
和Num a
是函数的附加输入。它们是一种特殊的输入:词典。当您将此函数与特定类型a
一起使用时,还必须有词典可用于类型Ord
上的Num
和a
操作同样。
任何使用带字典输入的函数的函数也必须具有相同的字典输入。
foo :: (Num a, Ord a) => a -> t
foo x = loop x someFunc someT
但是,您不必明确传递这些词典。假设有一本字典,Haskell会为你处理这个问题。您可以使用类型类实例创建字典。
instance Num MyType with
x + y = ...
x - y = ...
...
这会为Num
上的MyType
操作创建一个字典,因此MyType
可用于Num a
所需输入的任何位置(假设它满足其他要求,当然)。
答案 3 :(得分:1)
在=>
的左侧,您声明了右侧使用的类型的约束。
在您给出的示例中,这意味着a
被约束为Ord
类型类和Num
类型类的实例。