Scala Functor和Monad的区别

可以请某人解释在Scala上下文中Functor和Monad之间的区别吗?

斯卡拉本身并不强调FunctorMonad术语。 我想使用map是函子的一面,使用flatMap是Monad的一面。

对于我来说,使用scalaz进行查找和玩耍一直是得到scala环境中的这些function概念(与haskell环境相比)的最佳途径。 两年前,当我开始scala时,scalaz代码对我来说是无稽之谈,然后在几个月前我又开始寻找了,并且我意识到这真是一个干净的实现这种特殊风格的函数式编程。

例如, Monad实现表明monad是一个尖的函子,因为它扩展了Pointed特征(以及Applicative trait)。 我邀请你去看代码。 它有源码本身的链接,很容易遵循链接。

所以函数更一般。 Monads提供附加function。 要了解当你有一个函数时,或者当你有一个monad时你可以做什么,你可以看看MA

您将看到需要隐式函子的实用程序方法(特别是应用函子),例如sequence和某些需要完整monad的方法(如replicateM

scalaz为参考点,一个typesF[_] (也就是一个typesF被某种单一types参数化)是一个函子,如果一个函数可以被提取。 这是什么意思:

 class Function1W[A, B](self: A => B) { def lift[F[_]: Functor]: F[A] => F[B] } 

也就是说,如果我有一个函数A => B ,函子F[_] ,那么我现在有一个函数F[A] => F[B] 。 这实际上只是看scala的map方法的反向方法,它忽略了CanBuildFrom东西基本上是:

 F[A] => (A => B) => F[B] 

如果我有一个string列表,一个从String到Int的函数,那么我显然可以产生一个Ints列表。 这适用于选项,stream等,他们都是仿函数

我觉得有趣的是,你可能会立即跳到一个(错误的)结论:一个函子是A的一个“容器”。 这是一个不必要的限制。 例如,考虑一个函数X => A 如果我有一个函数X => A和一个函数A => B那么明确地说,通过构造,我有一个函数X => B 但是现在看这样看:

 type F[Y] = X => Y //F is fixed in X (X => A) andThen (A => B) is X => B F[A] A => BF[B] 

所以对于某个固定的X,typesX => A也是一个函子。 函子在scalaz中被devise为如下特征:

 trait Functor[F[_]] { def fmap[A, B](fa: F[A], f: A => B): F[B] } 

因此上面的Function1.lift方法被执行

 def lift[F[_]: Functor]: F[A] => F[B] = (f: F[A]) => implicitly[Functor[F]].fmap(f, self) 

几个函子实例:

 implicit val OptionFunctor = new Functor[Option] { def fmap[A, B](fa: Option[A], f: A => B) = fa map f } implicit def Functor1Functor[X] = new Functor[({type l[a]=X => a})#l] { def fmap[A, B](fa: X => B, f: A => B) = f compose fa } 

斯卡拉 ,monad的devise是这样的:

 trait Monad[M[_]] { def pure[A](a: A): M[A] //given a value, you can lift it into the monad def bind[A, B](ma: M[A], f: A => B): M[B] } 

这可能是什么用处并不是特别明显。 事实certificate,答案是“非常”。 我发现Daniel Spiewak的Monad并不是十分清楚地描述了为什么会出现这种情况,还有Tony Morris 通过monad读写器进行configuration ,这是一个很好的实例,说明在monad中编写程序可能意味着什么。

最好的文章详细地阐述了这两个概念是Eric Torreborre博客的 “ 迭代器模式的本质 ”。

函子

 trait Functor[F[_]] { def fmap[A, B](f: A => B): F[A] => F[B] } 
  • 一种解释Functor是将其描述为A型值的计算
    例如:
    • List[A]是返回Atypes(非确定性计算)的几个值的计算,
    • Option[A]用于您可能具有或不具有的计算,
    • Future[A]是一个计算你将会得到的typesA的值,等等。
  • 描绘它的另一种方式就是为A型值的某种“容器”

这是您定义的基本层:

  • PointedFunctor (创buildtypesF[A] )和
  • applic (提供方法applic ,作为容器F (F[A => B])内的计算值F (F[A => B]) ,应用于值F[A] ), Applicative FunctorApplicative FunctorPointedFunctor )。

所有这三个元素都用来定义一个Monad

前一阵子我写了: http : //gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html (虽然我不是专家)

首先要理解的是types'T [X]':这是一种“上下文”(对于types编码的东西是有用的,用这个“构成”它们)但是看到其他的答案:)

好吧,现在你的types在一个上下文中,比如说M [A](A在“M”里面),而你有一个普通的函数f:A => B …你不能继续使用它,因为函数期望A并且你有M [A]。 你需要一些方式来“解压缩”M的内容,应用function并再次“打包”。 如果你对M的内部知识有“亲密”的知识,那么你可以这样做,如果你把它推广到一个你以

 trait Functor[T[_]]{ def fmap[A,B](f:A=>B)(ta:T[A]):T[B] } 

而这正是一个函数。 它通过应用函数f将T [A]变换成T [B]。

Monad是神秘的生物,具有难以捉摸的理解力和多重隐喻,但是一旦你得到了应用函子,我发现它很容易理解:

函子允许我们在上下文中将函数应用于事物。 但是,如果我们要应用的function已经在上下文中呢? (如果你的函数需要多个参数,那么在这种情况下很容易结束)。

现在我们需要类似于函数的东西,但是也需要函数已经在上下文中,并将它们应用到上下文中的元素。 这就是应用函数。 这是签名:

 trait Applicative[T[_]] extends Functor[T]{ def pure[A](a:A):T[A] def <*>[A,B](tf:T[A=>B])(ta:T[A]):T[B] } 

到现在为止还挺好。 现在是monads:如果现在你有一个function,把事情的背景? 它的签名将是g:X => M [X] …您不能使用函子,因为它期望X => Y,所以我们将以M [M [X]]结束,您不能使用因为期望已经在上下文M [X => Y]中的函数。

因此,我们使用monad,它使用函数X => M [X],并且已经在上下文M [A]中,并将函数应用于上下文中的内容,只将结果打包到一个上下文中。 签名是:

 trait Monad[M[_]] extends Applicative[M]{ def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B] } 

它可以是相当抽象的,但如果你想如何使用“选项”,它会告诉你如何编写函数X => Option [X]

编辑:忘记配合它的重要事情:>> =符号被称为绑定,并在斯卡拉flatMap 。 (另外,作为一个方面说明,还有一些法则,仿函数,应用程序和单子必须遵循才能正常工作)。

我认为这个伟大的博客将帮助你第一个monadhttp://blog.enfranchisedmind.com/2007/08/a-monad-tutorial-for-ocaml/