Scala Functor 和 Monad 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8460594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala Functor and Monad differences
提问by dimitrisli
Can please someone explain the differences between Functor and Monad in the Scala context?
有人可以解释一下 Scala 上下文中 Functor 和 Monad 之间的区别吗?
采纳答案by huynhjl
Scala itself really does not emphasize the Functorand Monadterms that much. I guess using mapis the functor side, using flatMapis the Monad side.
Scala 本身并没有那么强调Functor和Monad术语。我猜 usingmap是函子端, usingflatMap是 Monad 端。
For me looking and playing around with scalazhas been so far the best avenue to get a sense of those functional concepts in the scala context (versus the haskell context). Two years ago when I started scala, the scalaz code was gibberish to me, then a few months ago I started looking again and I realized that it's really a clean implementation of that particular style of functional programming.
对我来说,到目前为止,在 scala 上下文(相对于 haskell 上下文)中了解这些函数式概念的最佳途径是使用scalaz。两年前,当我开始使用 scala 时,scalaz 代码对我来说是胡言乱语,然后几个月前我再次开始寻找,我意识到它确实是这种特定函数式编程风格的干净实现。
For instance the Monadimplementation shows that a monad is a pointed functorbecause it extends the Pointedtrait (as well as the Applicativetrait). I invite you to go look at the code. It has linking in the source itself and it's really easy to follow the links.
例如,Monad实现表明 monad 是一个指向函子,因为它扩展了Pointedtrait(以及Applicativetrait)。我邀请你去看看代码。它在源代码中具有链接,并且很容易跟踪链接。
So functors are more general. Monads provide additional features. To get a sense of what you can do when you have a functor or when you have a monad, you can look at MA
所以函子更通用。Monads 提供了额外的功能。要了解当你有一个函子或当你有一个 monad 时你可以做什么,你可以看看MA
You'll see utility methods that need an implicit functor (in particular applicative functors) such as sequenceand sometime methods that needs a full monad such as replicateM.
您将看到需要隐式函子(特别是应用函子)的实用程序方法,例如sequence有时需要完整 monad 的方法,例如replicateM.
回答by oxbow_lakes
Taking scalazas the reference point, a type F[_](that is, a type F which is parameterized by some single type) is a functor if a function can be lifted into it. What does this mean:
以scalaz为参考点,F[_]如果一个函数可以提升到一个类型(即由某个单一类型参数化的类型 F)是一个函子。这是什么意思:
class Function1W[A, B](self: A => B) {
def lift[F[_]: Functor]: F[A] => F[B]
}
That is, if I have a function A => B, a functor F[_], then I now have a function F[A] => F[B]. This is really just the reverse-way of looking at scala's mapmethod, which (ignoring the CanBuildFromstuff) is basically:
也就是说,如果我有一个函数A => B,一个函子F[_],那么我现在就有了一个函数F[A] => F[B]。这实际上只是查看 Scalamap方法的相反方式,它(忽略这些CanBuildFrom内容)基本上是:
F[A] => (A => B) => F[B]
If I have a List of Strings, a function from String to Int, then I can obviously produce a List of Ints. This goes for Option, Stream etc. They are all functors
如果我有一个字符串列表,一个从字符串到 Int 的函数,那么我显然可以生成一个 Int 列表。这适用于 Option、Stream 等。它们都是函子
What I find interesting about this is that you might immediately jump to the (incorrect) conclusion that a Functor is a "container" of As. This is an unnecesssary restriction. For example, think about a function X => A. If I have a function X => Aand a function A => Bthen clearly, by composition, I have a function X => B. But now, look at it this way:
我觉得有趣的是,您可能会立即得出(错误的)结论,即 Functor 是As的“容器” 。这是一个不必要的限制。例如,考虑一个函数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 => B F[B]
So the type X => A for some fixed X is also a functor. In scalaz, functor is designed as a trait as follows:
所以对于某个固定 X 的类型 X => A 也是一个函子。在scalaz 中,函子被设计为一个特征如下:
trait Functor[F[_]] { def fmap[A, B](fa: F[A], f: A => B): F[B] }
hence the Function1.liftmethod above is implemented
因此实现了Function1.lift上述方法
def lift[F[_]: Functor]: F[A] => F[B]
= (f: F[A]) => implicitly[Functor[F]].fmap(f, self)
A couple of functor instances:
几个函子实例:
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
}
In scalaz, a monad is designed like this:
在scalaz 中,一个 monad 是这样设计的:
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]
}
It is not particularly obvious what the usefulness of this might be. It turns out that the answer is "very". I found Daniel Spiewak's Monads are not Metaphorsextremely clear in describing why this might be and also Tony Morris's stuff on configuration via the reader monad, a good practical example of what might be meant by writing your program inside a monad.
这可能有什么用处并不是特别明显。事实证明,答案是“非常”。我发现 Daniel Spiewak 的Monads are not Metaphors非常清楚地描述了为什么会这样,还有 Tony Morris 的关于通过 reader monad进行配置的东西,这是一个很好的实例,说明在 monad 中编写程序可能意味着什么。
回答by GClaramunt
A while ago I wrote about that: http://gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html(I'm no expert though)
前段时间我写过这个:http: //gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html(虽然我不是专家)
The first thing to understand is the type ' T[X] ' : It's a kind of "context" (is useful to encode things in types and with this you're "composing" them) But see the other answers :)
首先要理解的是类型“T[X]”:它是一种“上下文”(对于将事物编码为类型很有用,因此您可以“组合”它们)但请参阅其他答案:)
Ok, now you have your types inside a context, say M[A] (A "inside" M), and you have a plain function f:A=>B ... you can't just go ahead and apply it, because the function expects A and you have M[A]. You need some way to "unpack" the content of M, apply the function and "pack" it again. If you have "intimate" knowledge of the internals of M you can do it, if you generalize it in a trait you end with
好的,现在你在一个上下文中拥有你的类型,比如 M[A](A“内部”M),你有一个普通的函数 f:A=>B ......你不能继续应用它,因为函数需要 A 而你有 M[A]。您需要某种方法来“解包” M 的内容,应用该函数并再次“打包”它。如果你对 M 的内部结构有“深入”的了解,你就可以做到,如果你把它概括为一个你结束的特征
trait Functor[T[_]]{
def fmap[A,B](f:A=>B)(ta:T[A]):T[B]
}
And that's exactly what a functor is. It transforms a T[A] into a T[B] by applying the function f.
而这正是函子的含义。它通过应用函数 f 将 T[A] 转换为 T[B]。
A Monad is a mythical creature with elusive understanding and multiple metaphors, but I found it pretty easy to understand once you get the applicative functor:
Monad 是一种神秘的生物,具有难以捉摸的理解和多种隐喻,但我发现一旦你获得了 applicative functor,它就很容易理解:
Functor allow us to apply functions to things in a context. But what if the functions we want to apply are already in a context? (And is pretty easy to end in that situation if you have functions that take more than one parameter).
函子允许我们将函数应用于上下文中的事物。但是如果我们想要应用的函数已经在一个上下文中呢?(如果您的函数采用多个参数,则很容易在这种情况下结束)。
Now we need something like a Functor but that also takes functions already in the context and applies them to elements in the context. And that's what the applicative functor is. Here is the signature:
现在我们需要像 Functor 这样的东西,但它也接受上下文中已有的函数并将它们应用于上下文中的元素。这就是应用函子。这是签名:
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]
}
So far so good. Now comes the monads: what if now you have a function that puts things in the context? It's signature will be g:X=>M[X] ... you can't use a functor because it expects X=>Y so we'll end with M[M[X]], you can't use the applicative functor because is expecting the function already in the context M[X=>Y] .
到现在为止还挺好。现在是 monads:如果现在你有一个将事物置于上下文中的函数怎么办?它的签名将是 g:X=>M[X] ... 你不能使用函子,因为它期望 X=>Y 所以我们将以 M[M[X]] 结尾,你不能使用applicative functor 因为期望函数已经在上下文 M[X=>Y] 中。
So we use a monad, that takes a function X=>M[X] and something already in the context M[A] and applies the function to what's inside the context, packing the result in only one context. The signature is:
所以我们使用一个 monad,它接受一个函数 X=>M[X] 和上下文 M[A] 中已经存在的东西,并将该函数应用于上下文中的内容,只将结果打包到一个上下文中。签名是:
trait Monad[M[_]] extends Applicative[M]{
def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B]
}
It can be pretty abstract, but if you think on how to work with "Option" it shows you how to compose functions X=>Option[X]
它可能非常抽象,但是如果您考虑如何使用“Option”,它会向您展示如何组合函数 X=>Option[X]
EDIT: Forgot the important thing to tie it: the >>= symbol is called bindand is flatMapin Scala. (Also, as a side note, there are some laws that functors, applicatives, and monads have to follow to work properly).
编辑:忘记了绑定它的重要事项:>>= 符号在 Scala 中称为bind并且是flatMap。(另外,作为旁注,函子、应用程序和单子必须遵循一些规律才能正常工作)。
回答by VonC
The best article laying out in details those two notions is "The Essence of the Iterator Pattern " from Eric Torreborre's Blog.
详细介绍这两个概念的最佳文章是来自Eric Torreborre 的博客的“迭代器模式的本质” 。
Functor
函子
trait Functor[F[_]] {
def fmap[A, B](f: A => B): F[A] => F[B]
}
- One way of interpreting a
Functoris to describe it as a computation of values of typeA.
For example:
List[A]is a computation returning several values of typeA(non-deterministic computation),Option[A]is for computations that you may or may not have,Future[A]is a computation of a value of typeAthat you will get later, and so on.- Another way of picturing it is as some kind of "container" for values of type A.
- 解释 a 的一种方法
Functor是将其描述为对 type 值的计算A。
例如:
List[A]是返回多个类型值的A计算(非确定性计算),Option[A]用于您可能有或可能没有的计算,Future[A]是对A稍后将获得的类型值的计算,依此类推。- 另一种描绘它的方式是作为A 类型值的某种“容器”。
It is the basic layer from which you define:
它是您定义的基本层:
PointedFunctor(to create a value of typeF[A]) andApplic(to provide a methodapplic, being a computed value inside the containerF (F[A => B]), to apply to a valueF[A]),Applicative Functor(aggregation of anApplicand aPointedFunctor).
PointedFunctor(创建一个类型的值F[A])和Applic(提供一个方法applic,作为容器内的计算值F (F[A => B]),应用于值F[A]),Applicative Functor(anApplic和 a 的聚合PointedFunctor)。
All three elements are used to define a Monad.
所有三个元素都用于定义一个Monad.
回答by Hymanson Tale
I think this great blog post will help you first for monad. http://blog.enfranchisedmind.com/2007/08/a-monad-tutorial-for-ocaml/
我认为这篇很棒的博文首先会帮助你monad。http://blog.enfranchisemind.com/2007/08/a-monad-tutorial-for-ocaml/

