## 动力学知识库

` 1 trait Monad[F[_]] extends Applicative[F] with Bind[F] { self => 2 //// scalaz/Monad.scala 3 4 override def map[A,B](fa: F[A])(f: A => B) = bind(fa)(a => point(f(a))) 5 ... 6 trait Applicative[F[_]] extends Apply[F] { self => 7 //// scalaz/Applicative.scala 8 def point[A](a: => A): F[A] 9 ...10 trait Apply[F[_]] extends Functor[F] { self =>11 //// scalaz/Apply.scala12 def ap[A,B](fa: => F[A])(f: => F[A => B]): F[B]13 ...14 trait Bind[F[_]] extends Apply[F] { self =>15 //// scalaz/Bind.scala1617 /** Equivalent to `join(map(fa)(f))`. */18 def bind[A, B](fa: F[A])(f: A => F[B]): F[B]1920 override def ap[A, B](fa: => F[A])(f: => F[A => B]): F[B] = {21 lazy val fa0 = fa22  bind(f)(map(fa0))23  }24 ...`

` 1 final class BindOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Bind[F]) extends Ops[F[A]] { 2 //// 3 import Liskov.<~<, Leibniz.=== 4 5 def flatMap[B](f: A => F[B]) = F.bind(self)(f) 6 7 def >>=[B](f: A => F[B]) = F.bind(self)(f) 8 9 def ∗[B](f: A => F[B]) = F.bind(self)(f)10 ...`

` 1 final class MonadOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Monad[F]) extends Ops[F[A]] { 2 //// 3 4 def liftM[G[_[_], _]](implicit G: MonadTrans[G]): G[F, A] = G.liftM(self) 5 6 def whileM[G[_]](p: F[Boolean])(implicit G: MonadPlus[G]): F[G[A]] = F.whileM(p, self) 7 8 def whileM_(p: F[Boolean]): F[Unit] = F.whileM_(p, self) 910 def untilM[G[_]](p: => F[Boolean])(implicit G: MonadPlus[G]): F[G[A]] = F.untilM(self, p)1112 def untilM_(p: => F[Boolean]): F[Unit] = F.untilM_(self, p)1314 def iterateWhile(p: A => Boolean): F[A] = F.iterateWhile(self)(p)1516 def iterateUntil(p: A => Boolean): F[A] = F.iterateUntil(self)(p)1718 ////19 }`

`1 // Functor : map[A,B] (F[A])(f: A => B): F[B]2 // Applicative: ap[A,B] (F[A])(f: F[A => B]): F[B]3 // Monad : flatMap[A,B](F[A])(f: A => F[B]): F[B]`

`1 // fa.flatMap(a => fb.flatMap(b => fc.flatMap(c => fd.map(...))))`

`1 // for {2 // a <- (fa: F[A])3 // b <- (fb: F[A])4 // c <- (fc: F[A])5 // } yield { ... }`

` 1 class Foo { def bar: Option[Bar] } 2 class Bar { def baz: Option[Baz] } 3 class Bar { def baz: Option[Baz] } 4 5 def compute(maybeFoo: Option[Foo]): Option[Int] = 6 maybeFoo.flatMap { foo => 7 foo.bar.flatMap { bar => 8 bar.baz.map { baz => 9  baz.compute10  }11  }12  }13 def compute2(maybeFoo: Option[Foo]): Option[Int] =14 for {15 foo <- maybeFoo16 bar <- foo.bar17 baz <- bar.baz18 } yield baz.compute`

`1 // ap[A,B](ma: F[A])(mf: F[A => B]): F[B] = mf.flatMap(f => ma.flatMap(a => point(f(a)))  `

`1 // map[A,B](fa: F[A])(f: A => B): F[B] = fa.flatMap(a => point(f(a))) `

`1 2.some flatMap {x => (x + 3).some } //> res0: Option[Int] = Some(5)2 2.some >>= { x => (x + 3).some } //> res1: Option[Int] = Some(5)3 (none: Option[Int]) >>= {x => (x + 3).some } //> res2: Option[Int] = None`

`1 Monad[Option].point(2) //> res3: Option[Int] = Some(2)2 Monad[Option].point(2) >>= {x => Monad[Option].point(x + 3)}3 //> res4: Option[Int] = Some(5)4 (None: Option[Int]) >>= {x => Monad[Option].point(x + 3)}5 //> res5: Option[Int] = None`

`1 type Discs = Int //杠铃片数量2 case class Barbell(left: Discs, right: Discs) {3 def loadLeft(n: Discs): Barbell = copy(left = left + n)4 def loadRight(n: Discs): Barbell = copy(right = right + n)5 }6 Barbell(0,0).loadLeft(1) //> res8: Exercises.monad.Barbell = Barbell(1,0)7 Barbell(1,0).loadRight(1) //> res9: Exercises.monad.Barbell = Barbell(1,1)8 Barbell(2,1).loadLeft(-1) //> res10: Exercises.monad.Barbell = Barbell(1,1)`

`1 Barbell(0,0).loadLeft(1).loadRight(2).loadRight(100).loadLeft(2).loadRight(-99)2 //> res11: Exercises.monad.Barbell = Barbell(3,3)`

` 1 type Discs = Int //杠铃片数量 2 case class Barbell(left: Discs, right: Discs) { 3 def loadLeft(n: Discs): Option[Barbell] = copy(left = left + n) match { 4 case Barbell(left,right) => if ( (left+right <= 20) && math.abs(left-right) <=3 ) Some(Barbell(left,right)) else None 5 case _ => None 6  } 7 def loadRight(n: Discs): Option[Barbell] = copy(right = right + n) match { 8 case Barbell(left,right) => if ( (left+right <= 20) && math.abs(left-right) <=3 ) Some(Barbell(left,right)) else None 9 case _ => None10  }11 }12 Barbell(0,0).loadLeft(1) //> res8: Option[Exercises.monad.Barbell] = Some(Barbell(1,0))13 Barbell(1,0).loadRight(1) //> res9: Option[Exercises.monad.Barbell] = Some(Barbell(1,1))14 Barbell(2,1).loadLeft(-1) //> res10: Option[Exercises.monad.Barbell] = Some(Barbell(1,1))15 Barbell(0,0).loadLeft(4) //> res11: Option[Exercises.monad.Barbell] = None16 Barbell(15,1).loadRight(15) //> res12: Option[Exercises.monad.Barbell] = None`

`1 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3)} //> res13: Option[Exercises.monad.Barbell] = Some(Barbell(3,3))2 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3) >>= {_.loadRight(1)}}3 //> res14: Option[Exercises.monad.Barbell] = Some(Barbell(3,4))4 Barbell(0,0).loadLeft(3) >>= {_.loadRight(3) >>= {_.loadRight(1) >>= {_.loadLeft(4)}}}5 //> res15: Option[Exercises.monad.Barbell] = Some(Barbell(7,4))6 Barbell(0,0).loadLeft(1) >>= {_.loadRight(5) >>= {_.loadLeft(2)}}7 //> res16: Option[Exercises.monad.Barbell] = None8 Monad[Option].point(Barbell(0,0)) >>= {_.loadLeft(3) >>= {_.loadRight(6)}}9 //> res17: Option[Exercises.monad.Barbell] = Some(Barbell(3,6))`

` 1 def addWeight: Option[Barbell] = for { 2 b0 <- Monad[Option].point(Barbell(0,0)) 3 b1 <- b0.loadLeft(3) 4 b2 <- b1.loadRight(3) 5 } yield b2 //> addWeight: => Option[Exercises.monad.Barbell] 6 addWeight //> res18: Option[Exercises.monad.Barbell] = Some(Barbell(3,3)) 7 8 def addWeight1: Option[Barbell] = for { 9 b0 <- Monad[Option].point(Barbell(0,0))10 b1 <- b0.loadLeft(4)11 b2 <- b1.loadRight(3)12 } yield b2 //> addWeight1: => Option[Exercises.monad.Barbell]13 addWeight1 //> res19: Option[Exercises.monad.Barbell] = None`