學習函數式編程時,每一個學習到這一章節的人都會寫一篇博客嘗試把本身的理解記錄下來編程
這好像是一個詛咒。從另外一方面講也證實了這一章節知識的難度之高。什麼Functor,什麼Monad在以前的工做和學習中壓根就沒有聽過這些東西。即使是看了一些講解的博客和書籍,感受仍是半知半解。這些概念的抽象程度實在過高了,涉及到了數學領域的範疇論。函數式編程
###Functor函數
函子(Functor):Functor表示範疇A與範疇B之間的映射。映射的是一種過程;範疇對應Scala中的高階類型T[]。在Scala中常見的高階類型有Option,集合類型,Function等。Functor的典型招式就是map,好比Some(5).map( + 1); List(1, 2, 3).map(_ + 1)。Function這個稍微有點區別,不是調用map函數,而是compose函數:學習
scala> val f1 = (x: Int) => x + 1 f1: Int => Int = <function1> scala> val f2 = (x: Int) => x + 1 f2: Int => Int = <function1> scala> f1.compose(f2) res2: Int => Int = <function1> scala> res2(1) res3: Int = 3
舉個例子:Some(3).map(_ + 3),Functor在背後作的事情是這樣的: ui
###Applicativescala
咱們把相似Option這一類值看成封裝過的值,Functor能夠把這類封裝過的值拆包,並執行函數映射。可是,當Function也是被包裝過期,Functor還能發揮做用嗎?看一個實驗:code
scala> val fop = Some((x: Int) => x * x) fop: Some[Int => Int] = Some(<function1>) scala> val op1 = Some(1) op1: Some[Int] = Some(1) scala> op1.map(fop _) <console>:10: error: type mismatch; found : () => Some[Int => Int] required: Int => ? op1.map(fop _) ^ scala> op1.map(o => fop.map(f => o)) res14: Option[Option[Int]] = Some(Some(1))
經過看上邊的log發現是不能夠的。其實經過代碼也能夠看出這是不可行的,op1是一個Option類型,若是執行內部函數應該使用map方法。經過map函數雖然能夠執行到函數可是返回值卻不是咱們指望的:Option[Option[Int]]
。OK,Applicative出場。博客
Applicative的做用是: 應用封裝過的函數到封裝過的值。正好使用咱們的適用場景。看代碼:數學
scala> val op1 = Some(1) op1: Some[Int] = Some(1) scala> val op2 = Some(2) op2: Some[Int] = Some(2) scala> for(o1 <- op1; o2 <- op2) yield o1 + o2 res7: Option[Int] = Some(3) scala> val fop = Some((x: Int) => x * x) fop: Some[Int => Int] = Some(<function1>) scala> for(f <- fop; o <- op1) yield f(o) res9: Option[Int] = Some(1)
接下來看一個看一個有意思的case;上邊說了Collection類型也能夠應用Functor。假如咱們把一組函數映射到一組值會發生什麼呢?io
scala> val f1 = (x: Int) => x + 1 f1: Int => Int = <function1> scala> val f2 = (x: Int) => x + 2 f2: Int => Int = <function1> scala> val fs = List(f1, f2) fs: List[Int => Int] = List(<function1>, <function1>) scala> for(f <- fs; x <- List(1, 2, 3)) yield f(x) res15: List[Int] = List(2, 3, 4, 3, 4, 5)
List(1, 2, 3)映射List(f1, f2)以後獲得了List(2, 3, 4, 3, 4, 5),很是神奇。
###Monad "說白了,Monad不就是自函子範疇上的幺半羣嘛"。話是這麼說,可是究竟能有多少人可以理解這個定義呢。光是自函子這個東西就足夠讓人抓狂了。從現實使用場景出發,Monad的招牌動做就是flatMap,表示一類可以被壓縮的東西。好比List(List(1), List(2)) flat 以後是 List(1, 2) , Some(Some(2)) flat以後是 Some(2)