## 动力学知识库

` 1 import scalaz._ 2 import Scalaz._ 3 object decompose { 4 //两个测试函数 5 val f = (_: Int) + 3 //> f : Int => Int = <function1> 6 val g = (_: Int) * 5 //> g : Int => Int = <function1> 7 //functor 8 val h = f map g // f andThen g //> h : Int => Int = <function1> 9 val h1 = g map f // f compose g //> h1 : Int => Int = <function1>10 h(2) //g(f(2)) //> res0: Int = 2511 h1(2) //f(g(2)) //> res1: Int = 1312 //applicative13 val k = (f |@| g){_ + _} //> k : Int => Int = <function1>14 k(10) // f(10)+g(10) //> res2: Int = 6315 //monad16 val m = g.flatMap{a => f.map(b => a+b)} //> m : Int => Int = <function1>17 val n = for {18 a <- f19 b <- g20 } yield a + b //> n : Int => Int = <function1>21 m(10) //> res3: Int = 6322 n(10) //> res4: Int = 6323 }`

`1 final case class Kleisli[M[_], A, B](run: A => M[B]) { self =>2 ...3 trait KleisliFunctions {4 /**Construct a Kleisli from a Function1 */5 def kleisli[M[_], A, B](f: A => M[B]): Kleisli[M, A, B] = Kleisli(f)6 ...`

(A=>M[B]) >=> (B=>M[C]) >=> (C=>M[D]) 最终运算结果M[D]

1、函数必需是 A => M[B]这种模式；只有一个输入，结果是一个Monad M[_]

2、上一个函数输出M[B]，他的运算值B就是下一个函数的输入。这就要求下一个函数的输入参数类型必需是B

` 1 /** alias for `andThen` */ 2 def >=>[C](k: Kleisli[M, B, C])(implicit b: Bind[M]): Kleisli[M, A, C] = kleisli((a: A) => b.bind(this(a))(k.run)) 3 4 def andThen[C](k: Kleisli[M, B, C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >=> k 5 6 def >==>[C](k: B => M[C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >=> kleisli(k) 7 8 def andThenK[C](k: B => M[C])(implicit b: Bind[M]): Kleisli[M, A, C] = this >==> k 910 /** alias for `compose` */11 def <=<[C](k: Kleisli[M, C, A])(implicit b: Bind[M]): Kleisli[M, C, B] = k >=> this1213 def compose[C](k: Kleisli[M, C, A])(implicit b: Bind[M]): Kleisli[M, C, B] = k >=> this1415 def <==<[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = kleisli(k) >=> this1617 def composeK[C](k: C => M[A])(implicit b: Bind[M]): Kleisli[M, C, B] = this <==< k`

kleisli((a: A) => b.bind(this(a))(k.run))的意思是先运算M[A]，接着再运算k，以M[A]运算结果值a作为下一个函数k.run的输入参数。整个实现过程并不复杂。

` 1 type ReaderT[F[_], E, A] = Kleisli[F, E, A] 2 val ReaderT = Kleisli 3 type =?>[E, A] = Kleisli[Option, E, A] 4 type Reader[E, A] = ReaderT[Id, E, A] 5 6 type Writer[W, A] = WriterT[Id, W, A] 7 type Unwriter[W, A] = UnwriterT[Id, W, A] 8 9 object Reader {10 def apply[E, A](f: E => A): Reader[E, A] = Kleisli[Id, E, A](f)11  }1213 object Writer {14 def apply[W, A](w: W, a: A): WriterT[Id, W, A] = WriterT[Id, W, A]((w, a))15  }1617 object Unwriter {18 def apply[U, A](u: U, a: A): UnwriterT[Id, U, A] = UnwriterT[Id, U, A]((u, a))19 }`

type ReaderT[F[_], E, A] = Kleisli[F, E, A] >>> type Reader[E,A] = ReaderT[Id,E,A]

` 1 //Kleisli款式函数kf,kg 2 val kf: Int => Option[String] = (i: Int) => Some((i + 3).shows) 3 //> kf : Int => Option[String] = <function1> 4 val kg: String => Option[Boolean] = { case "3" => true.some; case _ => false.some } 5 //> kg : String => Option[Boolean] = <function1> 6 //Kleisli函数组合操作 7 import Kleisli._ 8 val kfg = kleisli(kf) >=> kleisli(kg) //> kfg : scalaz.Kleisli[Option,Int,Boolean] = Kleisli(<function1>) 9 kfg(1) //> res5: Option[Boolean] = Some(false)10 kfg(0) //> res6: Option[Boolean] = Some(true)`

`1 // just some trivial data structure ,2 // Continents contain countries. Countries contain cities.3 case class Continent(name: String, countries: List[Country] = List.empty)4 case class Country(name: String, cities: List[City] = List.empty)5 case class City(name: String, isCapital: Boolean = false, inhabitants: Int = 20)`

` 1 val data: List[Continent] = List( 2 Continent("Europe"), 3 Continent("America", 4  List( 5 Country("USA", 6  List( 7 City("Washington"), City("New York"))))), 8 Continent("Asia", 9  List(10 Country("India",11 List(City("New Dehli"), City("Calcutta"))))))`

` 1 def continents(name: String): List[Continent] = 2 data.filter(k => k.name.contains(name)) //> continents: (name: String)List[Exercises.kli.Continent] 3 //查找名字包含A的continent 4 continents("A") //> res7: List[Exercises.kli.Continent] = List(Continent(America,List(Country(U 5 //| SA,List(City(Washington,false,20), City(New York,false,20))))), Continent(A 6 //| sia,List(Country(India,List(City(New Dehli,false,20), City(Calcutta,false,2 7 //| 0)))))) 8 //找到两个：List(America,Asia) 9 def countries(continent: Continent): List[Country] = continent.countries10 //> countries: (continent: Exercises.kli.Continent)List[Exercises.kli.Country]11 //查找America下的国家12 val america =13 Continent("America",14  List(15 Country("USA",16  List(17 City("Washington"), City("New York")))))18 //> america : Exercises.kli.Continent = Continent(America,List(Country(USA,Lis19 //| t(City(Washington,false,20), City(New York,false,20)))))20 countries(america) //> res8: List[Exercises.kli.Country] = List(Country(USA,List(City(Washington,f21 //| alse,20), City(New York,false,20))))22 def cities(country: Country): List[City] = country.cities23 //> cities: (country: Exercises.kli.Country)List[Exercises.kli.City]24 val usa = Country("USA",25  List(26 City("Washington"), City("New York")))27 //> usa : Exercises.kli.Country = Country(USA,List(City(Washington,false,20),28 //| City(New York,false,20)))29 cities(usa) //> res9: List[Exercises.kli.City] = List(City(Washington,false,20), City(New Y30 //| ork,false,20))`

String => List[Continent]

Continent => List[Country]

Country => List[City]

` 1 val allCountry = kleisli(continents) >==> countries 2 //> allCountry : scalaz.Kleisli[List,String,Exercises.kli.Country] = Kleisli(< 3 //| function1>) 4 val allCity = kleisli(continents) >==> countries >==> cities 5 //> allCity : scalaz.Kleisli[List,String,Exercises.kli.City] = Kleisli(<functi 6 //| on1>) 7 allCountry("Amer") //> res10: List[Exercises.kli.Country] = List(Country(USA,List(City(Washington, 8 //| false,20), City(New York,false,20)))) 9 allCity("Amer") //> res11: List[Exercises.kli.City] = List(City(Washington,false,20), City(New10 //| York,false,20))`

`1 def =<<(a: M[A])(implicit m: Bind[M]): M[B] = m.bind(a)(run)`

`1 allCity =<< List("Amer","Asia") //> res12: List[Exercises.kli.City] = List(City(Washington,false,20), City(New2 //| York,false,20), City(New Dehli,false,20), City(Calcutta,false,20))`

List[String] => Option[List[Continent]]

List[Continent] => Option[List[Country]]

List[Country] => Option[List[City]]

` 1 //查找Continent List[String] => Option[List[Continent]] 2 def maybeContinents(names: List[String]): Option[List[Continent]] = 3 names.flatMap(name => data.filter(k => k.name.contains(name))) match { 4 case h :: t => (h :: t).some 5 case _ => none 6 } //> maybeContinents: (names: List[String])Option[List[Exercises.kli.Continent]] 7 //| 8 //测试运行 9 maybeContinents(List("Amer","Asia")) //> res13: Option[List[Exercises.kli.Continent]] = Some(List(Continent(America,10 //| List(Country(USA,List(City(Washington,false,20), City(New York,false,20))))11 //| ), Continent(Asia,List(Country(India,List(City(New Dehli,false,20), City(Ca12 //| lcutta,false,20)))))))13 //查找Country List[Continent] => Option[List[Country]]14 def maybeCountries(continents: List[Continent]): Option[List[Country]] =15 continents.flatMap(continent => continent.countries.map(c => c)) match {16 case h :: t => (h :: t).some17 case _ => none18 } //> maybeCountries: (continents: List[Exercises.kli.Continent])Option[List[Exer19 //| cises.kli.Country]]20 //查找City List[Country] => Option[List[Country]]21 def maybeCities(countries: List[Country]): Option[List[City]] =22 countries.flatMap(country => country.cities.map(c => c)) match {23 case h :: t => (h :: t).some24 case _ => none25 } //> maybeCities: (countries: List[Exercises.kli.Country])Option[List[Exercises.26 //| kli.City]]2728 val maybeAllCities = kleisli(maybeContinents) >==> maybeCountries >==> maybeCities29 //> maybeAllCities : scalaz.Kleisli[Option,List[String],List[Exercises.kli.Cit30 //| y]] = Kleisli(<function1>)31 maybeAllCities(List("Amer","Asia")) //> res14: Option[List[Exercises.kli.City]] = Some(List(City(Washington,false,232 //| 0), City(New York,false,20), City(New Dehli,false,20), City(Calcutta,false,33 //| 20)))`