通过前面的几篇讨论我们了解到F[T]就是FP中运算的表达形式(representation of computation).在这里F[]不仅仅是一种高阶类型,它还代表了一种运算协议(computation protocol)或者称为运算模型好点,如IO[T],Option[T].运算模型规范了运算值T的运算方式.而Monad是一种特殊的FP运算模型M[A],它是一种持续运算模式.通过flatMap作为链条把前后两个运算连接起来.多个flatMap同时作用可以形成一个程序运行链.我们可以在flat…
中间插播了几篇scalaz数据类型,现在又要回到Monad专题.因为FP的特征就是Monad式编程(Monadic programming),所以必须充分理解认识Monad.熟练掌握Monad运用.曾经看到一段对Monad的描述:“Monadic for-comprehension就是一种嵌入式编程语言,由它的Monad提供它的语法”.但如果每一种Monad的for-comprehension都独立提供一套语法的话,这种编程语言就显得十分单调.功能简单了.那么既然是FP,我们应该可以通过函数组合…
Monad Reader就是一种函数的组合.在scalaz里函数(function)本身就是Monad,自然也就是Functor和applicative.我们可以用Monadic方法进行函数组合: import scalaz._ import Scalaz._ object decompose { //两个测试函数 val f = (_: Int) + //> f : Int => Int = <function1> val g = (_: Int) * //> g : In…
说道FP,我们马上会联想到Monad.我们说过Monad的代表函数flatMap可以把两个运算F[A],F[B]连续起来,这样就可以从程序的意义上形成一种串型的流程(workflow).更直白的讲法是:任何类型只要实现了flatMap就可以用for-comprehension, for{...}yield.在这个for{...}里我们可以好像OOP一样编写程序.这个for就是一种运算模式,它规范了在for{...}里指令的行为.我们正从OOP风格走入FP编程模式,希望有个最基本的FP编程模式使我…
我们经常提到函数式编程就是F[T].这个F可以被视为一种运算模式.我们是在F运算模式的壳子内对T进行计算.理论上来讲,函数式程序的运行状态也应该是在这个运算模式壳子内的,也是在F[]内更新的.那么我们就应该像函数式运算T值一样,也有一套函数式更新程序状态的方法.之前我们介绍了Writer Monad.Writer也是在F[]内维护Log的,可以说是一种状态维护方式.但Writer的Log是一种Monoid类型,只支持Semigroup的a|+|b操作,所以只能实现一种两段Log相加累积这种效果.…
scala标准库提供了一个Either类型,它可以说是Option的升级版.与Option相同,Either也有两种状态:Left和Right,分别对应Option的None和Some,不同的是Left可以返回一个值.我们通常用这个值来表述异常信息.scalaz也提供了自己版本的Either,并用\/来分辨表示,以及两种状态-\/和\/-.我想scalaz特别提供\/是有原因的:\/不单是一种类型,它是一种type class.更重要的是\/是一种Monad,具备了函数组合能力(composib…
在上一篇讨论里我们简单的介绍了一下Cake Pattern和Reader Monad是如何实现依赖注入的.主要还是从方法上示范了如何用Cake Pattern和Reader在编程过程中解析依赖和注入依赖.考虑到依赖注入模式在编程中的重要性和普遍性,觉着还需要再讨论的深入一些,使依赖注入模式在FP领域里能从理论走向实际.既然我们正在scalaz的介绍系列里,所以这篇我们就着重示范Reader Monad的依赖注入方法. 再说明一下依赖注入:我们说过在团队协作开发里能够实现软件模块的各自独立开发,原…
我们可以用Monad Reader来实现依赖注入(dependency injection DI or IOC)功能.Scala界中比较常用的不附加任何Framework的依赖注入方式可以说是Cake Pattern了.现在通过Monad Reader可以实现同样功能,两者对比优点各有千秋.所谓依赖注入是指在编程时使用了某个未知实现细节的对象,但依赖注入确保这个对象在这段程序运行时已经实例化.这种需求通常是在大型软件开发时对项目进行模块化分割后虽然模块之间互有依赖,但又可以同步开发.特别是在多人…
在前面的几篇讨论里我们初步对FP有了些少了解:FP嘛,不就是F[A]吗?也是,FP就是在F[]壳子(context)内对程序的状态进行更改,也就是在F壳子(context)内施用一些函数.再直白一点就是在F壳子内进行OOP惯用的行令编程(imperative programming).当然,既然是在壳子(context)内进行编程这种新的模式,那么总需要些新的函数施用方法吧.我们再次审视一下以前了解过的FP函数施用方法: // Functor : map[A,B] (F[A])(f: A =>…
前面提到了scalaz是个函数式编程(FP)工具库.它提供了许多新的数据类型.拓展的标准类型及完整的一套typeclass来支持scala语言的函数式编程模式.我们知道:对于任何类型,我们只需要实现这个类型的typeclass实例就可以在对这个类型施用所对应typeclass提供的所有组件函数了(combinator).突然之间我们的焦点好像都放在了如何获取typeclass实例上了,从而忽略了考虑为什么要使用这些typeclass及使用什么样的typeclass这些问题了.所以可能有人会问我:…