为什么我们需要monads? [英] Why do we need monads?

查看:107
本文介绍了为什么我们需要monads?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的愚见中,着名问题的答案是什么是monad? ,尤其是最被投票的人,试图解释什么是monad,而没有明确地解释monad为什么非常必要。他们可以解释为一个问题的解决方案吗?

解决方案

为什么我们需要单子?




  1. 我们只想使用函数编写 。 (毕竟是函数式编程(FP))。然后,我们遇到了第一个大问题。这是一个程序:

    f(x)= 2 * x




    $ b

    g(x,y)= x / y

    >什么是首先执行
    ?我们如何使用不超过函数形成一个有序的函数序列(即程序



    解决方案:撰写功能。如果你想首先 g 然后 f ,只需写下 f(g(x,y ))。这样,程序也是一个函数: main = f(g(x,y))。好的,但... ... $ / $>

  2. 更多问题:一些函数可能会失败(即 g(2, 0),除以0)。我们在FP中有 noexceptions(一个例外不是函数)。解决方案:让我们允许函数返回两种东西:而不是让 g> :真实,真实 - >真正的(从两个实数到真实的函数),让我们让 g:Real,Real - >真实|没有什么(从两个实数到实数或无)的函数)。 但是函数应该(更简单)只返回一件事。解决方案:让我们创建一个新的要返回的数据类型,一个拳击类型,它可能包含一个真实的或者没有任何内容。因此,我们可以有 g:Real,Real - >也许真正。好的,但是...

  3. f 尚未准备好使用也许是Real 。而且,我们不想改变每一个可以连接 g 的函数来消费一个 Maybe Real 。 p>

    解决方案:让我们具有连接/撰写/链接功能的特殊功能。这样,我们可以在幕后调整一个函数的输出来输入下面的函数。

    在我们的例子中: g>> = f (connect / compose g f )。我们希望>> = 来获得 g 的输出,检查它,如果它是 Nothing 只是不要调用 f 并返回 Nothing ;或者相反,用它提取盒装的 Real 并提供 f 。 (这个算法只是>> = Maybe 类型的实现)。还要注意,>> = 必须每个装箱类型(不同的箱子,不同的适配算法)写入一次

    >
  4. 使用相同的模式可以解决许多其他问题:1.使用盒子来编码/存储不同的含义/值,并具有 g 返回这些装箱值。 2.有一个作曲家/连结器 g>> = f 来帮助连接 g 的输出到 f 的输入,所以我们不必改变任何 f


  5. 使用这种技术可以解决的显着问题是:具有全局状态的


    • 函数序列中的每个函数(程序)都可以共享:解决方案 StateMonad 我们不喜欢不纯的函数:为相同的输入产生不同的输出的函数。因此,让我们标记这些函数,使它们返回一个标记/装箱值: IO monad。



总幸福!


In my humble opinion the answers to the famous question "What is a monad?", especially the most voted ones, try to explain what is a monad without clearly explaining why monads are really necessary. Can they be explained as the solution to a problem?

解决方案

Why do we need monads?

  1. We want to program only using functions. ("functional programming (FP)" after all).
  2. Then, we have a first big problem. This is a program:

    f(x) = 2 * x

    g(x,y) = x / y

    How can we say what is to be executed first? How can we form an ordered sequence of functions (i.e. a program) using no more than functions?

    Solution: compose functions. If you want first g and then f, just write f(g(x,y)). This way, "the program" is a function as well: main = f(g(x,y)). OK, but ...

  3. More problems: some functions might fail (i.e. g(2,0), divide by 0). We have no "exceptions" in FP (an exception is not a function). How do we solve it?

    Solution: Let's allow functions to return two kind of things: instead of having g : Real,Real -> Real (function from two reals into a real), let's allow g : Real,Real -> Real | Nothing (function from two reals into (real or nothing)).

  4. But functions should (to be simpler) return only one thing.

    Solution: let's create a new type of data to be returned, a "boxing type" that encloses maybe a real or be simply nothing. Hence, we can have g : Real,Real -> Maybe Real. OK, but ...

  5. What happens now to f(g(x,y))? f is not ready to consume a Maybe Real. And, we don't want to change every function we could connect with g to consume a Maybe Real.

    Solution: let's have a special function to "connect"/"compose"/"link" functions. That way, we can, behind the scenes, adapt the output of one function to feed the following one.

    In our case: g >>= f (connect/compose g to f). We want >>= to get g's output, inspect it and, in case it is Nothing just don't call f and return Nothing; or on the contrary, extract the boxed Real and feed f with it. (This algorithm is just the implementation of >>= for the Maybe type). Also note that >>= must be written only once per "boxing type" (different box, different adapting algorithm).

  6. Many other problems arise which can be solved using this same pattern: 1. Use a "box" to codify/store different meanings/values, and have functions like g that return those "boxed values". 2. Have a composer/linker g >>= f to help connecting g's output to f's input, so we don't have to change any f at all.

  7. Remarkable problems that can be solved using this technique are:

    • having a global state that every function in the sequence of functions ("the program") can share: solution StateMonad.

    • We don't like "impure functions": functions that yield different output for same input. Therefore, let's mark those functions, making them to return a tagged/boxed value: IO monad.

Total happiness!

这篇关于为什么我们需要monads?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆