Traversables
的必要基石。<*>
与fmap
来将任何元数的函数“提升”以适用于应用值。也就是说,您可以将任何a -> b -> c -> d
转换为Applicative f => f a -> f b -> f c -> f d
。您还可以查看Data.Traversable
和Data.Foldable
,它们包含几个涉及应用函子的通用函数。
Alternative
是一种特殊的应用函子,支持在可能“失败”的备选项之间进行选择(“空”确切含义取决于应用函子实例)。应用函子解析器是一个很好的实际例子,其中some
和many
的定义非常直观(例如,匹配某个模式零次或多次或一次或多次)。
单子是最有趣和最有用的类型类之一,但已经有其他答案详细介绍了它们。
Monoid
是另一个既简单又立即有用的类型类。它基本上定义了一种将两个数据合并在一起的方式,这样就可以获得一个通用的concat
以及在前面提到的Foldable
模块中的功能,并且它还使您能够使用Writer
单子与数据类型一起使用。
在Haskell中,许多标准函数需要它们的参数实现一个或多个类型类。在您的代码中这样做,可以使其他开发人员(或者您自己)以已经熟悉的方式使用您的数据,而无需编写额外的函数。
例如,实现Ord类型类将允许您使用诸如sort、min、max等功能。否则,您需要使用sortBy等函数。
是的,这意味着实现类型类Foo
会为你提供所有其他具有Foo
约束的函数“免费”使用。
Functor
类型类在这方面并不太有趣,因为它没有给你很多东西。
一个更好的例子是单子和Control.Monad
模块中的函数。一旦你为你的类型定义了两个Monad
函数(>>=)
和return
,你就可以使用另外30多个函数来处理你的类型。
其中一些更有用的函数包括:mapM
、sequence
、forever
、join
、foldM
、filterM
、replicateM
、when
、unless
和liftM
。这些函数在Haskell代码中经常出现。
如果你将“接口和实现”替换为“类型类和实例”,那么你的面向对象直觉就可以延续下去。如果你将新类型C作为标准类型类B的一个实例,那么你就可以免费获得你的类型能够与所有依赖于B的现有代码A一起使用的功能。
正如其他人所说,当类型类是像
Monad
这样的东西时,那么免费赠品就是许多库函数,例如foldM
和when
。
guard
需要MonadPlus
。 - Daniel Fischer