使用Functors或其他类型类免费获得哪些功能?

时间:2012-01-09 07:50:10

标签: haskell typeclass functor

我读了article说:

  

为许多标准类型类[Functors]提供实例将立即为您提供许多实用免费的功能

我的问题是:你可以免费获得这个功能(对于仿函数或其他类型类)?我知道仿函数的定义是什么,但是通过将某些东西定义为仿函数/其他类型类,我可以获得 free 。除了更漂亮的语法之外的东西。理想情况下,这将是基于仿函数/其他类型类的一般和有用的函数。

我的想象(可能是错误的)自由意味着什么是这种功能:TypeClass x => useful x y = ..

==编辑/添加==

我想我主要是询问更抽象(和令人难以置信的)类型类,如this image中的类型类。对于像Ord这样不太抽象的类,我的面向对象的直觉理解。

6 个答案:

答案 0 :(得分:9)

Functors很简单,可能不是最好的例子。让我们来看看Monads:

  • liftM - 如果某些内容是Monad,则它也是liftMfmap的Functor。
  • >=><=<:您可以免费撰写a -> m b个函数,m是您的monad。
  • foldM, mapM, filterM ...你得到了一堆实用函数来概括现有函数以使用你的monad。
  • when guard *和unless - 您还可以免费获得一些控制功能。
  • join - 这实际上是monad定义的基础,但是你不需要在Haskell中定义它,因为你定义了>>=
  • 变形金刚 - ErrorT和东西。您可以将错误处理方法固定到新类型上,免费(提供或接受)!

基本上,只要您将Monad实例设置为Functor,就可以“提升”使用新类型的各种标准函数。将它变为Applicativeguard也变得微不足道(但不是自动的)。

然而,这些都是更一般的想法的“症状”。您可以编写适用于所有 monad的有趣,重要的代码。您可能会发现您为类型编写的一些函数 - 无论出于何种原因,这些函数在您的特定情况下都很有用 - 可以推广到所有monad。现在你可以突然接受你的功能,并在解析器,列表,maybes和......上使用它。

*正如Daniel Fischer所指出的那样,MonadPlus需要Monad而不是{{1}}。

答案 1 :(得分:5)

Functors本身并不是很有趣,但它们是进入应用仿函数和Traversables的必要踏脚石。

使应用仿函数有用的主要属性是,您可以使用fmap与应用运算符<*>来“提升”任何arity的任何函数以使用应用值。即您可以将a -> b -> c -> d转换为Applicative f => f a -> f b -> f c -> f d。您还可以查看Data.TraversableData.Foldable,其中包含几个涉及应用仿函数的通用函数。

Alternative是一个专门的应用程序函数,它支持在“失败”的替代方案之间进行选择(“空”的确切含义取决于应用实例)。应用解析器是一个实际示例,其中somemany的定义非常直观(例如,匹配某些模式零次或多次或一次或多次)。

Monads是最有趣和最有用的类型类之一,但其他答案已经很好地涵盖了它们。

Monoid是另一个既简单又立即有用的类型类。它基本上定义了一种方法,将两个数据组合在一起,然后在前面提到的concat模块中为您提供通用Foldable和功能,并且它还允许您使用Writer具有数据类型的monad。

答案 2 :(得分:4)

haskell中有许多标准函数要求它们的参数实现一个或多个类型类。在代码中这样做允许其他开发人员(或您自己)以他们已经熟悉的方式使用您的数据,而无需编写其他功能。

例如,实现Ord类型将允许您使用sort,min,max等内容。否则,您将需要sortBy等。

答案 3 :(得分:4)

是的,这意味着实现类型类Foo会为您提供免费Foo约束的所有其他函数。

Functor类型在这方面并不太有趣,因为它不会给你很多。

更好的例子是monad和Control.Monad模块中的函数。在为您的类型定义了两个Monad函数(>>=)return之后,您将获得另外三十个函数,然后可以在您的类型上使用。

一些更实用的内容包括:mapMsequenceforeverjoinfoldMfilterM,{{1 },replicateMwhenunless。这些在Haskell代码中一直显示出来。

答案 4 :(得分:2)

正如其他人所说,Functor本身实际上并没有免费获得更多。基本上,类型类更高级或更通用(意味着更多的东西适合该描述),那么你将获得的“免费”功能越少。因此,例如,Functor和Monoid不会为您提供太多,但Monad和Arrow为您提供了许多免费的有用功能。

在Haskell中,为Functor和Monoid编写实例仍然是一个好主意(如果你的数据类型确实是一个仿函数或一个monoid),因为我们几乎总是在编写函数时尝试使用最通用的接口。如果您正在编写一个只能使用fmap来操作数据类型的新功能,那么没有理由将该功能人为地限制为MonadApplicative s,因为它可能在以后用于其他事情。

答案 5 :(得分:1)

如果您阅读“类型类和实例”的“接口和实现”,那么您的面向对象的直觉就会存在。如果你将新类型C作为标准类型类B的一个实例,那么你可以免费获得你的类型将适用于依赖于B的所有现有代码A.

  

UML diagram

正如其他人所说,当类型类似于Monad时,免费赠品就是许多库函数,如foldMwhen