你见过C,JAVA之类的命令式语言提过Monad的概念吗? 只有Haskell,只要学Haskell就逃不了理解Monad,因为它是pure的。 monad 上图的”(+3)”就是一个函数,对输入的值加上3,再输出。
还是不理解,如果只是为了连续操作,函数连续嵌套调用不就行了吗? 简单说,Monad就是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤。 你只要提供下一步运算所需的函数,整个运算就会自动进行下去。 monad monad 它不是值与值的运算,也不是值与数据类型的运算,而是数据类型与数据类型的运算。
monad: IO Monad
之前找了很多文章,也一直未明白,不过这个monad的学习之前,有一个cps的概念可能会更好一些。 因为”(+3)”这个函数是处理值的(简称”值函数”),而不是处理数据类型的。 最初我是通过Javascript了解异步编程方式,回过头来一看,其Promise也是一个Monad,然而Future概念也收到Promise里去了。 我们站在haskell的环境中,首先明确数据类型是有值的,例如Int这个数据类型从数量上讲有无限个值,可能的值:3,7,999…
它接受”值函数”和数据类型的实例作为输入参数,使用”值函数”处理后,再输出数据类型的另一个实例。 既然Future是对未来的预期,当下可能没有值,自然拿不到值,但是我们可以通过bind操作将处理值的动作串起来带入Future的世界里,将来某个时间点执行这个动作,这也是以同步方式写异步代码! monad FP的Monad概念完美解决了传统语言异步编程需要挂各种回调的难处。 好在Monad提供了一种友好的方式,毕竟程序猿更加能接受的是符合直觉的串行代码,而不是回调嵌套代码。
monad: 图解 Monad
首先,取出它们各自的值,一个是函数,一个是数值;然后,使用函数处理数值;最后,将函数的返回结果再封装进数据类型。 这个表达式的类型是IO (),对输入的数乘以二操作也被隔离在IO Monad的世界里了,普通函数没法直接拿到IO世界里的值,必须得将函数lift到这个世界里与其共舞。 同样的由于Monad确定了控制流,保证了按代码顺序执行,先getLine后print。 monad 终于写到最后了,其实我们用了很久的Monad,不同的Monad背后高度一致性,将控制流封装起来,从而提高代码的可读性。 应用多了回头理解抽象的Monad概念,其实也不是那么难了,之后理解这类概念就更加得心应手了,这也是抽象之美。
丢了Maybe,跟“数据类型”相关的都不太好理解了。 我看文章,一直不知道3为什么不是数据类型,看了原文才知道,不是“数据类型”,而是“maybe数据类型”。 前者用于构造Maybe Monad,后者用于串联一系列Maybe类型,避免写一堆if/match、取值语句,况且从Maybe取出其不存在的值是有可能抛异常的。 Monad概念最初来自于范畴论,后来引入进函数式编程语言,由函数式编程发扬光大,渐渐渗透到其他主流语言中。 非常感谢,这篇文章终于让我明白了monad。
monad: Monad定义
而且真正图解monad部分的马桶搋子也没有放过来。。。 结果绝大部分篇幅讲functor和Applicative。
这两个操作可以这样理解,定义个Monad类型用于包裹另一个类型T,同时定义一个二元操作,左边对象是个 Monad,右边对象是个函数接受被包裹的 monad T 值并返回一个 Monad对象,这样就能不断通过这个二元操作串起来。 而在现实世界里,很多东西就必须是有顺序的,比如输入输出。 于是Haskell决定用monad去模拟这种操作。 Monad来源于范畴论,他并不解决副作用问题本身,而是对此类问题提供了抽象。
monad: 文章被以下专栏收录
有时候我们需要对每一步操作进行日志记录,简单起见,但是不想每次操作后进行日志拼接工作,若抽象成Monad,可以让bind帮我们完成这个操作,这节我打算用Javascript来快速实现个原型,方便熟悉Javascript的同学理解。 在FP中一切都是纯函数,那么对于IO这种拥有副作用的功能,怎么融入到FP的世界中去呢? 有了IO Monad包裹了对IO的操作动作,副作用被约束在Monad中,同时也提供了与外界环境交互的边界。 冲(+3)函数是用来处理值的,和“值函数”私加引号这些上下文语句,阮老师所讲的值函数应该是普通意义上“值函数”,亦即,函数在运行时就是用来处理值的,而(+3)可能处理的是Int类型的值。
(+3)是不完全函数,它是某一种函数类型,它的输入和输出都有类型约束—Num这个类型类(Num类型类来自于haskell的概念),这个类型类有许多实例类型,如:Int,Float等,亦即,输入输出的数据类型可以是Num的实例类型。 那么Future做成一个Monad会怎么样? Unit操作就是通过Promise得到Future,而bind二元操作就是输入一个Future和动作,该动作可以拿到未来的值T,进行处理后返回一个新Future,这样就能将各个Future串起来。 @corper,谁告诉你Monad可以简化IO操作的? Monad最大的作用就是在pure 函数式编程中处理副作用。
monad: 图解 Monad
数据类型就是对值的一种封装,不仅包括值本身,还包括相关的属性和方法。 上图就是2的封装,从此2就不是一个单纯的值,而是一种数据类型的实例,只能在数据类型的场景(context)中使用。 而bind二元操作,对应于Promise的then接口,传递一个动作执行,返回一个Promise,从而能将各个Promise串起来。 从博主的描述看monad只是个概念,其他语言使用都可以实现并且有相关的库(但不会提及这个术语),楼上提到的flatMap是一个经典使用场景。 原文中是把数值封装到Maybe这样的特殊数据类型里。
- 还是不理解,如果只是为了连续操作,函数连续嵌套调用不就行了吗?
- 它接受”值函数”和数据类型的实例作为输入参数,使用”值函数”处理后,再输出数据类型的另一个实例。
- 而且真正图解monad部分的马桶搋子也没有放过来。。。
- 最初我是通过Javascript了解异步编程方式,回过头来一看,其Promise也是一个Monad,然而Future概念也收到Promise里去了。
- 既然Future是对未来的预期,当下可能没有值,自然拿不到值,但是我们可以通过bind操作将处理值的动作串起来带入Future的世界里,将来某个时间点执行这个动作,这也是以同步方式写异步代码!