## 动力学知识库

`1 def ask(prompt: String): String = {2 println(prompt)3 readLine4 }5 def tell(msg: String): Unit = println(msg)6 for {7 name <- ask("what's your name?")8 _ <- tell(s"I'm \$name")9 } yield()`

` 1 trait MyIO[+A] {self =>2 def run: A3 def map[B](f: A => B): MyIO[B] =4 new MyIO[B] {5 def run = f(self.run)6 }7 def flatMap[B](f: A => MyIO[B]): MyIO[B] =8 new MyIO[B] {9 def run = f(self.run).run10 }11 }12 object MyIO {13 def apply[A](a: A) = new MyIO[A] { def run = a }14 implicit val ioMonad = new Monad[MyIO] {15 def point[A](a: => A) = new MyIO[A] { def run = a }16 def bind[A,B](ma: MyIO[A])(f: A => MyIO[B]): MyIO[B] =17 ma flatMap f18 }19 }`

` 1 import MyIO._2 def ask(prompt: String): MyIO[String] =3 MyIO {4 println(prompt)5 readLine6 }7 def tell(msg: String): MyIO[Unit] =8 MyIO {9 println(msg)10 }`

`1 val org: MyIO[Unit] = for {2 first <- ask("What's your first name?")3 last <- ask("What's your last name?")4 _ <- tell(s"Hello \$first \$last!")5 } yield()`

` 1 object MyIOApp extends App {2 import MyIOFunctions._3 pr.run4 }5 //运算结果：6 What's your first name?7 Tiger8 What's your last name?9 Chan10 Hello Tiger Chan!`

` 1 package demo.app2 import scalaz._3 import Scalaz._45 trait MyIO[+A] {self =>6 def run: A7 def map[B](f: A => B): MyIO[B] =8 new MyIO[B] {9 def run = f(self.run)10 }11 def flatMap[B](f: A => MyIO[B]): MyIO[B] =12 new MyIO[B] {13 def run = f(self.run).run14 }15 }16 object MyIO {17 def apply[A](a: A) = new MyIO[A] { def run = a }18 implicit val ioMonad = new Monad[MyIO] {19 def point[A](a: => A) = new MyIO[A] { def run = a }20 def bind[A,B](ma: MyIO[A])(f: A => MyIO[B]): MyIO[B] =21 ma flatMap f22 }23 }24 object MyIOFunctions {25 import MyIO._26 def ask(prompt: String): MyIO[String] =27 MyIO {28 println(prompt)29 readLine30 }31 def tell(msg: String): MyIO[Unit] =32 MyIO {33 println(msg)34 }35 val prg: MyIO[Unit] = for {36 first <- ask("What's your first name?")37 last <- ask("What's your last name?")38 _ <- tell(s"Hello \$first \$last!")39 } yield()404142 }43 object MyIOApp extends App {44 import MyIOFunctions._45 prg.run46 }`

`sealed abstract class IO[A] {private[effect] def apply(rw: Tower[IvoryTower]): Trampoline[(Tower[IvoryTower], A)].../** Continues this action with the given function. */def map[B](f: A => B): IO[B] = io(rw =>apply(rw) map {case (nw, a) => (nw, f(a))})/** Continues this action with the given action. */def flatMap[B](f: A => IO[B]): IO[B] = io(rw =>apply(rw) flatMap {case (nw, a) => f(a)(nw)}).../** Construct an IO action from a world-transition function. */def io[A](f: Tower[IvoryTower] => Trampoline[(Tower[IvoryTower], A)]): IO[A] =new IO[A] {private[effect] def apply(rw: Tower[IvoryTower]) = Free(() => f(rw))}`

`object IO extends IOInstances {def apply[A](a: => A): IO[A] =io(rw => return_(rw -> a))...`

`/** Suspend the given computation in a single step. */def return_[S[_], A](value: => A)(implicit S: Applicative[S]): Free[S, A] =liftF[S, A](S.point(value))`

`sealed abstract class IO[A] {private[effect] def apply(rw: Tower[IvoryTower]): Trampoline[(Tower[IvoryTower], A)]import IO._/*** Runs I/O and performs side-effects. An unsafe operation.* Do not call until the end of the universe.*/def unsafePerformIO(): A = apply(ivoryTower).run._2`

`1 val hello = print("hello ").point[IO] //> hello : scalaz.effect.IO[Unit] = [email protected]2 val world = IO (print("world,")) //> world : scalaz.effect.IO[Unit] = [email protected]3 val howareyou = io {rw => return_(rw -> println("how are you!"))}4 //> howareyou : scalaz.effect.IO[Unit] = [email protected]5 val greeting = hello |+| world |+| howareyou //> greeting : scalaz.effect.IO[Unit] = [email protected]6 greeting.unsafePerformIO //> hello world,how are you!`

` 1 import scalaz._2 import Scalaz._3 import effect._4 import IO._5 import Free._6 import scala.language.higherKinds7 import scala.language.implicitConversions89 object IOPrg {10 def div(dvdn: Int, dvsor: Int): IO[Int] =11 IO(dvdn / dvsor)12 val ioprg: IO[Int] = for {13 _ <- putLn("enter dividend:")14 dvdn <- readLn15 _ <- putLn("enter divisor:")16 dvsor <- readLn17 quot <- div(dvdn.toInt, dvsor.toInt)18 _ <- putLn(s"the result:\$quot")19 } yield quot20 }2122 object IOMonadDemo extends App {23 import IOPrg._24 ioprg.unsafePerformIO()25 }`

`"enter dividend:"10"enter divisor:"5"the result:2"`

` 1 implicit def ioToOptionT[A](io: IO[A]): OptionT[IO,A] = io.liftM[OptionT]2 val optionIOprg: OptionT[IO,Int] = for {3 _ <- putLn("enter dividend:")4 dvdn <- readLn5 _ <- putLn("enter divisor:")6 dvsor <- readLn7 quot <- div(dvdn.toInt, dvsor.toInt)8 _ <- putLn(s"the result:\$quot")9 } yield quit10 ...11 object IOMonadDemo extends App {12 import IOPrg._13 // ioprg.unsafePerformIO()14 optionIOprg.run.unsafePerformIO()15 }16 ...17 "enter dividend:"18 1019 "enter divisor:"20 521 "the result:2"`

` 1 val optionIOprg: OptionT[IO,Int] = for {2 _ <- putLn("enter dividend:").liftM[OptionT]3 dvdn <- readLn.liftM[OptionT]4 _ <- putLn("enter divisor:").liftM[OptionT]5 dvsor <- readLn.liftM[OptionT]6 a <- if (dvsor.toInt == 0 ) OptionT(IO(None: Option[String])) else IO(0).liftM[OptionT]7 quot <- div(dvdn.toInt, dvsor.toInt).liftM[OptionT]8 _ <- putLn(s"the result:\$quot").liftM[OptionT]9 } yield quit10 ...11 "enter dividend:"12 1013 "enter divisor:"14 515 "the result:2"1617 Process finished with exit code 018 ...19 "enter dividend:"20 1021 "enter divisor:"22 02324 Process finished with exit code 0`

` 1 type WriterTIO[F[_],A] = WriterT[F,List[String],A]2 val writerIOprg: WriterT[IO,List[String],Int] = for {3 _ <- putLn("enter dividend:").liftM[WriterTIO]4 dvdn <- readLn.liftM[WriterTIO]5 _ <- WriterT.writerT((List(s"received dividend \$dvdn"),dvdn).point[IO])6 _ <- putLn("enter divisor:").liftM[WriterTIO]7 dvsor <- readLn.liftM[WriterTIO]8 _ <- WriterT.writerT(IO(List(s"received divisor \$dvsor, ready to divide ..."),dvdn))9 quot <- div(dvdn.toInt, dvsor.toInt).liftM[WriterTIO]10 _ <- putLn(s"the result:\$quot").liftM[WriterTIO]11 } yield quit12 ...13 object IOMonadDemo extends App {14 import IOMonadPrg._15 // ioprg.unsafePerformIO()16 //optionIOprg.run.unsafePerformIO()17 println(writerIOprg.run.unsafePerformIO())18 }19 ...20 "enter dividend:"21 1022 "enter divisor:"23 524 "the result:2"25 (List(received dividend 10, received divisor 5, ready to divide ...),2)2627 Process finished with exit code 0`

` 1 type WriterTIO[F[_],A] = WriterT[F,List[String],A]2 val writerIOprg: WriterT[IO,List[String],Int] = for {3 _ <- putLn("enter dividend:").liftM[WriterTIO]4 dvdn <- readLn.liftM[WriterTIO]5 _ <- WriterT.writerT((List(s"received dividend \$dvdn;"),dvdn).point[IO])6 _ <- putLn("enter divisor:").liftM[WriterTIO]7 dvsor <- readLn.liftM[WriterTIO]8 _ <- WriterT.writerT(IO(List(s"received divisor \$dvsor, ready to divide ..."),dvdn))9 quot <- div(dvdn.toInt, dvsor.toInt).except(e => IO({println(e.getMessage());-99})).liftM[WriterTIO]10 _ <- if (quot < 0) WriterT.writerT((List(s"divide by zero Error!!!"),-99).point[IO]) else putLn(s"the result:\$quot").liftM[WriterTIO]11 } yield (quot)12 ...13 object IOMonadDemo extends App {14 import IOMonadPrg._15 // ioprg.unsafePerformIO()16 //optionIOprg.run.unsafePerformIO()17 println(writerIOprg.run.unsafePerformIO())18 ...19 "enter dividend:"20 321 "enter divisor:"22 023 / by zero24 (List(received dividend 3;, received divisor 0, ready to divide ..., divide by zero Error!!!),-99)2526 Process finished with exit code 0`

` /** Executes the handler if an exception is raised. */def except(handler: Throwable => IO[A]): IO[A] =io(rw => try { Free.pure(this(rw).run) } catch { case e: Throwable => handler(e)(rw) })/*** Executes the handler for exceptions that are raised and match the given predicate.* Other exceptions are rethrown.*/def catchSome[B](p: Throwable => Option[B], handler: B => IO[A]): IO[A] =except(e => p(e) match {case Some(z) => handler(z)case None => throw e})/*** Returns a disjunction result which is right if no exception was raised, or left if an* exception was raised.*/def catchLeft: IO[Throwable \/ A] =map(\/.right[Throwable, A]) except (t => IO(-\/(t)))/**Like "catchLeft" but takes a predicate to select which exceptions are caught. */def catchSomeLeft[B](p: Throwable => Option[B]): IO[B \/ A] =catchLeft map (_.leftMap(e => p(e).getOrElse(throw e)))/**Like "finally", but only performs the final action if there was an exception. */def onException[B](action: IO[B]): IO[A] = this except (e => for {_ <- actiona <- (throw e): IO[A]} yield a)`

` 1 package demo.app23 import scalaz._4 import Scalaz._5 import effect._6 import IO._7 import Free._8 import scala.language.higherKinds9 import scala.language.implicitConversions1011 object IOMonadPrg {12 def div(dvdn: Int, dvsor: Int): IO[Int] =13 IO(dvdn / dvsor)14 val ioprg: IO[Int] = for {15 _ <- putLn("enter dividend:")16 dvdn <- readLn17 _ <- putLn("enter divisor:")18 dvsor <- readLn19 quot <- div(dvdn.toInt, dvsor.toInt)20 _ <- putLn(s"the result:\$quot")21 } yield quot22 //implicit def ioToOptionT[A](io: IO[A]): OptionT[IO,A] = io.liftM[OptionT]23 val optionIOprg: OptionT[IO,Int] = for {24 _ <- putLn("enter dividend:").liftM[OptionT]25 dvdn <- readLn.liftM[OptionT]26 _ <- putLn("enter divisor:").liftM[OptionT]27 dvsor <- readLn.liftM[OptionT]28 a <- if (dvsor.toInt == 0 ) OptionT(IO(None: Option[String])) else IO(0).liftM[OptionT]29 quot <- div(dvdn.toInt, dvsor.toInt).liftM[OptionT]30 _ <- putLn(s"the result:\$quot").liftM[OptionT]31 } yield quot32 type WriterTIO[F[_],A] = WriterT[F,List[String],A]33 val writerIOprg: WriterT[IO,List[String],Int] = for {34 _ <- putLn("enter dividend:").liftM[WriterTIO]35 dvdn <- readLn.liftM[WriterTIO]36 _ <- WriterT.writerT((List(s"received dividend \$dvdn;"),dvdn).point[IO])37 _ <- putLn("enter divisor:").liftM[WriterTIO]38 dvsor <- readLn.liftM[WriterTIO]39 _ <- WriterT.writerT(IO(List(s"received divisor \$dvsor, ready to divide ..."),dvdn))40 quot <- div(dvdn.toInt, dvsor.toInt).except(e => IO({println(e.getMessage());-99})).liftM[WriterTIO]41 _ <- if (quot < 0) WriterT.writerT((List(s"divide by zero Error!!!"),-99).point[IO]) else putLn(s"the result:\$quot").liftM[WriterTIO]42 } yield (quot)434445 }4647 object IOMonadDemo extends App {48 import IOMonadPrg._49 // ioprg.unsafePerformIO()50 //optionIOprg.run.unsafePerformIO()51 println(writerIOprg.run.unsafePerformIO())52 }`