【发布时间】:2012-02-26 21:38:56
【问题描述】:
我是 Haskell 的新手,一般来说,我还是函数式编程的新手,我对它的语法有点不适应。
在以下代码中,=> 表示什么?还有(Num a, Ord a)?
loop :: (Num a, Ord a) => a -> (t -> t) -> t -> t
【问题讨论】:
我是 Haskell 的新手,一般来说,我还是函数式编程的新手,我对它的语法有点不适应。
在以下代码中,=> 表示什么?还有(Num a, Ord a)?
loop :: (Num a, Ord a) => a -> (t -> t) -> t -> t
【问题讨论】:
这是一个类型类约束; (Num a, Ord a) => ... 表示loop 可以与a 的任何类型一起使用,它是Num 和Ord 类型类的实例,分别对应于数字类型和有序类型。基本上,您可以将loop 视为具有=> 右侧的类型,但a 必须是Num 和Ord 的实例。
您可以认为类型类与 OOP 接口基本相似(但它们不是一回事!)——它们封装了一组任何实例都必须支持的定义,并且可以使用这些定义编写通用代码。例如,Num 包括加法和乘法等数字运算,而Ord 包括小于、大于等。
有关类型类的更多信息,请参阅Learn You a Haskell 中的this introduction。
【讨论】:
=> 分隔类型签名的两部分:
因此您可以将(Num a, Ord a) => a -> (t -> t) -> t -> t 视为“类型为a -> (t -> t) -> t -> t 并且必须有a 的Num 实例和a 的Ord 实例”。
有关类型类的更多信息,请参阅http://www.learnyouahaskell.com/types-and-typeclasses
【讨论】:
一种思考方式是Ord a 和Num a 是函数的附加输入。它们是一种特殊的输入:字典。当您将此函数用于特定类型a 时,还必须有字典可用于a 类型上的Ord 和Num 操作。
任何使用带有字典输入的函数的函数也必须具有相同的字典输入。
foo :: (Num a, Ord a) => a -> t
foo x = loop x someFunc someT
但是,您不必明确传递这些字典。假设有可用的字典,Haskell 会为您处理这些。您可以使用 typeclass 实例创建字典。
instance Num MyType with
x + y = ...
x - y = ...
...
这将为MyType 上的Num 操作创建一个字典,因此MyType 可以在Num a 是必需输入的任何地方使用(当然,假设它满足其他要求)。
【讨论】:
在=> 的左侧,您为右侧使用的类型声明约束。
在您给出的示例中,这意味着a 被限制为Ord 类型类和Num 类型类的实例。
【讨论】: