在上一篇讨论里我们简单的介绍了一下Cake Pattern和Reader Monad是如何实现依赖注入的。...既然我们正在scalaz的介绍系列里,所以这篇我们就着重示范Reader Monad的依赖注入方法。 ...): 1 object OnOffDevice { 2 def on: Reader[OnOffDevice, String] = Reader(_.on) 3 def off: Reader...[OnOffDevice, String] = Reader(_.off) 4 } 由于只有一个依赖,我们可以直接申明功能Reader,把on,off两个函数变成Primitive Reader。...由于Reader是个Monad,我们可以用map这样写: 1 object OnOffDevice { 2 def onOffDevice: Reader[OnOffDevice,OnOffDevice
我们可以用Monad Reader来实现依赖注入(dependency injection DI or IOC)功能。...现在通过Monad Reader可以实现同样功能,两者对比优点各有千秋。所谓依赖注入是指在编程时使用了某个未知实现细节的对象,但依赖注入确保这个对象在这段程序运行时已经实例化。...我们下面通过一个实际例子来示范Cake Pattern和Monad Reader是如何实现依赖注入的: 我们来模拟一个咖啡机开关场景:有一个电炉,可开(on)可关(off)。...那么用Monad Reader可以实现同样的依赖注入功能吗?...似乎Monad Reader的依赖注入方式简单直接些。
我们知道要如何 map over Maybe a,[a] 以及 IO a。我们甚至还知道如何用 a -> b map over r -> a,并且会得到 r -> b。...applicative values,Maybe a 代表可能会失败的 computation,[a] 代表同时有好多结果的 computation (non-deterministic computation),而 IO...其实 do 并不只是可以用在 IO,他可以用在任何 monad 上。他的原则是简单明了,把 monadic value 串成一串。我们这边来细看 do 是如何使用,以及为什么我们十分倚赖他。...WoM" >>= (\x -> [x,x,x]) ["WoM","WoM","WoM"] ghci> (\x -> [x,x,x]) "WoM" ["WoM","WoM","WoM"] 至于 IO...所以这个定律对于 IO 也是有效的。
Monad Reader就是一种函数的组合。在scalaz里函数(function)本身就是Monad,自然也就是Functor和applicative。...在FP里这样的函数组合就是Monadic Reader。 但是FP里函数运算结果一般都是M[R]这样格式的,所以我们需要对f:A => M[B],g:B => M[C]这样的函数进行组合。...实际上Reader就是Kleisli的一个特殊案例:在这里kleisli的M[]变成了Id[],因为Id[A]=A >>> A=>Id[B] = A=>B,就是我们上面提到的Reader,我们看看Reader...输出Monad一致统一,都是Option。 那么,Kleisli到底用来干什么呢?它恰恰显示了FP函数组合的真正意义:把功能尽量细分化,通过各种方式的函数组合实现灵活的函数重复利用。...Option是个Monad,第一步可以通过。
中间插播了几篇scalaz数据类型,现在又要回到Monad专题。因为FP的特征就是Monad式编程(Monadic programming),所以必须充分理解认识Monad、熟练掌握Monad运用。...比如这样:Option[A] >>> IO[Option[A]] >>> IO[Either[String,Option[A]]。恰恰,Monad是不支持函数组合的。...但想深一层,如果其中一个Monad是会产生副作用的如IO[Option[A]],那么上面的例子就变成这样: 1 for { 2 optionData <- IO 3 } yield { 4 for...{ 5 data <- optionData 6 } yield Process(data) 7 } 我们看到在第一层运算里进行了IO运算,产生了副作用。...之前我们曾经讨论过 ReaderWriterState Monad,它是Reader,Writer,State三个Monad的组合。
Monad不就是个自函子范畴上的幺半群,这有什么难理解的(A monad is just a monoid in the category of endofunctors) —— Phillip Wadler...接着我们看看在自函子的范畴上,怎么结合幺半群的定义得出Monad的。...在Haskell这类的强类型语言中,我们甚至可以组装自己的Tuple Monad。...中缀表达式一般是 >>= Tuple >>= (Number -> Tuple) >>= (Number -> Tuple) Monads for functional programming一书中介绍说monad...Monads for functional programming Functor, Applicative, Monad
我们知道,任何涉及IO的运算都会面临堆栈溢出问题。这是因为IO通常针对无法预计的数据量以及重复循环操作。所以IO算法设计也会采用与Trampoline一样的数据结构。...或者我们应该沿用Trampoline数据结构和算法来设计IO组件库。如此思考那么我们就必须对Trampoline进行深度抽象了。Free Monad就是Trampline的延伸。...包括IO操作,也就是说可以进行一些含有副作用(side effect)的操作。那么这个函数是无法实现函数组合(function composition)。...既然我们在本篇命题里提到Free Monad是Monad生产线。那么用Free Monad能不能把Interact变成Monad呢?...如果我们用Free Monad来解决IO问题的话,堆栈溢出问题也是无法避免的。我们应该考虑在Free Monad里使用Trampoline类型。
函数式编程有一个重要概念,叫做Monad。 网上有很多解释(这里和这里),但都很抽象,不容易看懂。我尝试了好多次,还是不明白Monad到底是什么。...下面,我就用这些图来解释Monad。 1. 软件最基本的数据,就是各种值(value)。 2. 处理值的一系列操作,可以封装成函数。输入一个值,会得到另一个值。...所有这些运算连起来,就叫做Monad。 简单说,Monad就是一种设计模式,表示将一个运算过程,通过函数拆解成互相连接的多个步骤。你只要提供下一步运算所需的函数,整个运算就会自动进行下去。 (完)
更重要的是\/是一种Monad,具备了函数组合能力(composibility)。如此能够方便把Either功能整合到FP编程中去。
IO Monad就是泛函编程处理副作用代码的一种手段。...泛函模式的IO编程就是把IO功能表达和IO副作用产生分开设计:IO功能描述使用基于IO Monad的Monadic编程语言,充分利用函数组合进行。...在上面我们已经实现了map和flatMap函数,所以这个IO类型就是个Monad。...我们可以用Free Monad的结构替代IO类型结构,这样我们就可以用Monadic编程语言来描述IO程序。...在以上例子里我们采用了Id Monad作为Interpreter语言。Id Monad的flatMap不做任何事情,所以IO程序被直接对应到基本IO函数readLine, println上了。
monad 是支持>>=操作的 applicative 函子,>>=读作绑定,它的类型是: (>>=) :: (Monad m) => m a -> (a -> m b) -> m b 即取一个 monad...和一个函数,返回一个新的 monad。...monad 有专属的类型类——Monad,其定义如下: class Applicative m => Monad (m :: * -> *) where (>>=) :: m a -> (a ->...>>=前面说过了,>>有一个默认实现,就是把一个 monad 直接换成另一个 monad 返回,fail不会被主动调用,在一些特定语法结构中,会被 Haskell 用于模式匹配。...一个类型要成为 monad 不仅要满足 Monad 类型类的条件,还要满足 monad 定律(虽然编译器并不会帮你检查): 左单位元:return x >>= f 和 f x 等价 右单位元:m >>=
那么真正意义的状态类型State Monad又是怎样的呢?...State Monad应该需要一套读写、传递状态的方法。...类但并没有实现Monad的抽象函数point和bind。...Trampoline就是Free Monad的一个特殊案例,我们后面会详细介绍Free Monad。...这个细节就留在后面我们讨论Free Monad时再研究吧。
看到函数式编程相关的资料的时候, 总是看到 Monad 这个词, 一直想了解一下, 然而查资料对 Monad 的定义往往是上来一大堆数学概念: Monad 是一个自函子范畴上的幺半群 鉴于本人数学基础实在太差...Monad 并不仅局限于函数式编程语言, 也可以用其他的语言来表示....标准的 Monad 库提供了几种预定义好的常用 monad(也就是 unit 和 bind 函数), 可以直接拿来用....在声明式的语言中, 他被用来实现命令式语言中的 日志和 IO 操作. 在命令式的语言中, 他可以用来减少和隔离冗余的胶水代码....本文只是简单地介绍 了 Monad 的一些只管解释, 还可以查看下面这些资料: Monad on Wikipedia Monads in Python List of Monad tutorials 本文主要翻译自
Monad 定义 Monad 使用场景 Monad 一句话解释 Monad 定义 根据维基百科的定义,Monad 由以下三个部分组成: 一个类型构造函数(M),可以构建出一元类型 M。...Ok,我们已经明白了 Monad 的内部结构,接下来,我们再看一下 Monad 的使用场景。 Monad 使用场景 通过 Monad 的规则,衍生出了许多使用场景。 组装多个函数,实现链式操作。...包裹异步 IO 等副作用函数,放在最后一步执行。 还记得 Jquery 时代的 ajax 操作吗?...Monad?...总结 本文从 Monad 的维基百科开始,逐步介绍了 Monad 的内部结构以及实现原理,并通过 Promise 验证了 Monad 在实战中发挥的重大作用。
一.从Functor到Monad 从类型来看,Functor到Applicative再到Monad是从一般到特殊的递进过程(Monad是特殊的Applicative,Applicative是特殊的Functor...Applicative值就是计算,比如: Maybe a代表可能会失败的computation,[a]代表同时有好多结果的computation(non-deterministic computation),而IO...已经足够应付所有情况了 二.Monad typeclass class Applicative m => Monad m where (>>=) :: forall a b. m a ->...换言之,Monad就是支持>>=操作的Applicative functor而已 return是pure的别名,所以仍然是接受一个普通值并把它放进一个最小的context中(把普通值包进一个Monad里面...keyword Monad laws Explanation of Monad laws
于是现在我们知道 Maybe 既是 Functor 、又是 Applicative 还是 Monad。 现在我们来看看另一个例子:IO monad: ?...注: 由于 Kotlin 并不区分纯函数与非纯函数,因此根本不需要 IO monad。...这只是一个模拟: data class IO(val `(-`: T) infix fun IO.`))=`(f: ((T) -> IO)): IO =...fun getLine(): IO = IO(readLine() ?: "") readFile 接受一个字符串(文件名)并返回该文件的内容: ?...fun putStrLn(str: String): IO = IO(println(str)) 所有这三个函数都接受普通值(或无值)并返回一个已包装的值。
有一些相对于OOP来说不太一样的概念,比如 Applicative, Functor 以及今天的主题 Monad. 如果单纯的从字面上来看,很神秘,完全不知道其含义。...我的理解很简单,Functor是实现了map函数的容器,Monad 就是实现了 flatMap 方法的容器,比如在Swift里,Optional, CollectionType 等等都可以称为 Monad...map vs flatMap map 和 flatMap 的共同点都是接受一个 transform 函数,把一个容器转换为另外一个容器。
Monad当然复杂的多。...换言之IO Monad的用户是无法自定义算法(interpreter)的。...IO Monad可以使我们更方便地在IO这个壳子里进行我们熟悉的行令编程(imperative programming),因为我们只需要把行令程序直接放进IO里就行了。...所以我们说IO Monad就是在FP模式中进行行令编程的通用方式。可以想象我们可能会在IO这个壳子内进行我们熟悉的程序编写。那么IO Monad到底能不能符合在FP环境内的行令编程要求呢?...我们需要在IO[A]这种Monad之上增加Option的作用,可以用Monad Transformer来实现: 1 implicit def ioToOptionT[A](io: IO[A]):
And by the way, also a monad?...to be precise: 1 2 3 interface Monad<T,M extends Monad<?...In Java pseudo-syntax it would look somewhat like this: 1 2 3 4 5 Monad liftM2(Monad t1, Monad...monad we actually use....monad of a list of that type.
在IO操作中,这个优势还可以变得更加的明显。Haskell采用Monad实现IO相关的API,这个Monad就称为IO Monad。...通过Do表记可以写出很多符合直觉的代码,比如 main :: IO () main = do putStrLn "Hello" putStr "Plz enter your name: "...Haskell中的IO函数都会返回一个IO Monad,而上面的代码中,我们并没有对每一条都使用之前的结果。对于部分IO Monad(如putStrLn返回的),我们直接就抛弃了这些返回值。...而Monad的计算流程是可变的,这也意味着它的计算有“上下文”。一般的计算场景中都是有上下文的,比如IO运算。但是这种没有依赖的计算场景其实也是存在的,比如并发、Parser。...而且ZipList实际上是没有合法的Monad实现的。这里的合法不是说你实现Monad会报错,而是说你写的任意Monad都不符合Monad必须符合的定律。
领取专属 10元无门槛券
手把手带您无忧上云