泛函编程(33)-泛函IO:Free Functor

  • 时间:
  • 浏览:10
  • 来源:uu快3计划师_uu快3app苹果_全天计划

讲老实话,我到现在还很难想出要怎样实现你你这个map函数。除非把Console类型修改一下,你你这个可不须要参考前面讨论中的代码。

亲戚亲戚朋友同样可不须要用有2个多 类型来表示:

当然,这也导致 不可能 :有个类型B,有2个多 函数(B => A),A是任意类型,有2个多 F[B],F是任意Functor,亲戚亲戚朋友肯定能得出F[A]:不可能 亲戚亲戚朋友要怎样让我把(B => A)和F[B]传入map:

type FreeC[S[_],A] = Free[({type f[x] = Coyoneda[F,x]})#f, A]

不要再 正确地维护具体情况。

def liftF[S[_],A](sa: S[A])(implicit S: Functor[S]),这里的S就是Coyoneda。

也很顺利呢。再试试加了State维护的IO程序运行运行:

 1 case class State[S,A](runState: S => (A,S)) {
 2     def map[B](f: A => B) = State[S,B](s => {
 3         val (a1,s1) = runState(s)
 4         (f(a1),s1)
 5     })
 6     def flatMap[B](f: A => State[S,B]) = State[S,B](s => {
 7         val (a1,s1) = runState(s)
 8         f(a1).runState(s1)
 9     })
10 }
11 case class InOutLog(inLog: List[String], outLog: List[String])
12 type LogState[A] = State[InOutLog, A]
13 implicit val logStateMonad = new Monad[LogState] {
14     def unit[A](a: A) = State(s => (a, s))
15     def flatMap[A,B](sa: LogState[A])(f: A => LogState[B]) = sa flatMap f
16 }                                                 //> logStateMonad  : ch13.ex11.Monad[ch13.ex11.LogState] = ch13.ex11$$anonfun$m
17                                                   //| ain$1$$anon$11@3dd3bcd
18 object MockConsole extends(Console ~> LogState) {
19     def apply[A](c: Console[A]): LogState[A] = State(
20         s => (c,s) match {
21             case (GetLine, InOutLog(in,out)) => (in.head, InOutLog(in.tail, out))
22           case (PutLine(l), InOutLog(in,out)) => ((),InOutLog(in, l :: out))
23         })
24 }
25 val s = Free.runFC(ioprg)(MockConsole)            //> s  : ch13.ex11.LogState[Unit] = State(<function1>)
26 val ls = s.runState(InOutLog(List("Tiger","Chan"),List()))
27                                                   //> ls  : (Unit, ch13.ex11.InOutLog) = ((),InOutLog(List(),List(Hello, Tiger Ch
28                                                   //| an !, What is your last name ?, What is your first name ?)))

现在亲戚亲戚朋友可不须要直接用任何F[A]来产生Free了。先试试里边的那个Console。你你这个Console都有个Functor:

亲戚亲戚朋友把前面推导出来的Free搬过来。要怎样让在Free companion object里增加了FreeC类型:

你你这个可不须要说是有2个多 由Coyoneda产生的Free。

 map(fb: F[B])(f: B => A): F[A]。

 在前几期讨论中亲戚亲戚朋友终于推导出了Free Monad。这是有2个多 Monad工厂,它可不须要把任何F[A]变成Monad。可惜的是它对F[A]是有所要求的:F须就是个Functor。Free Monad由此被称为由Functor F 产生的Monad。F须就是Functor,你你这个门槛使亲戚亲戚朋友在使用Free Monad时很不方便。举个前面讨论过的例子:

现在亲戚亲戚朋友要想土措施把S[A]升格成FreeC:liftFC[S[_],A](s: S[A]): FreeC[S,A],这里须要先把S[A]升格成Coyoneda:Coyoneda(s)。

 可不须要使用Free的Monadic语言了。下面再试试Interpreter每段:

 1 val ioprg = for {
 2     _ <- PutLine("What is your first name ?")
 3     first <- GetLine
 4     _ <- PutLine("What is your last name ?")
 5     last <- GetLine
 6     _ <- PutLine(s"Hello, $first $last !")
 7 } yield ()                                        //> ioprg  : ch13.ex11.Free[[x]ch13.ex11.Coyoneda[ch13.ex11.Console,x],Unit] = 
 8                                                   //| Suspend(ch13.ex11$Coyoneda$$anon$4@13c78c0b)
 9 
10 type Id[A] = A
11 implicit val idMonad = new Monad[Id] {
12     def unit[A](a: A) = a
13     def flatMap[A,B](fa: A)(f: A => B): B = f(fa)
14 }                                                 //> idMonad  : ch13.ex11.Monad[ch13.ex11.Id] = ch13.ex11$$anonfun$main$1$$anon$
15                                                   //| 10@12843fce
16 
17 object RealConsole extends (Console ~> Id) {
18     def apply[A](ca: Console[A]): A = ca match {
19         case GetLine => readLine
20         case PutLine(l) => println(l)
21     }
22 }
23 Free.runFC(ioprg)(RealConsole)                    //> What is your first name ?/

在下面亲戚亲戚朋友可不须要证明F[A]同等Coyoneda[F,A],而Coyoneda是个Functor。亲戚亲戚朋友只需将F[A]升格(lift)到Coyoneda就能得到有2个多 Free Functor了。

 1 trait Functor[F[_]] {
 2     def map[A,B](fa: F[A])(f: A => B): F[B]
 3 }
 4 object Functor {
 5     def apply[F[_]: Functor]: Functor[F] = implicitly[Functor[F]]
 6 }
 7 trait Monad[M[_]] {
 8     def unit[A](a: A): M[A]
 9     def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B]
10     def map[A,B](ma: M[A])(f: A => B) = flatMap(ma)(a => unit(f(a)))
11 }
12 object Monad {
13     def apply[M[_]: Monad]: Monad[M] = implicitly[Monad[M]]
14 }
15 trait Yoneda[F[_],A] { yo =>
16     def apply[B](f: A => B): F[B]
17     def run: F[A] = apply(a => a)  //不要再Functor实例就可不须要将Yoneda转变成F[A]
18     def toCoyoneda: Coyoneda[F,A] = new Coyoneda[F,A] { //转Coyoneda不要再Functor
19         type I = A
20         def fi = yo.run
21         def k(i: A) = i
22     }
23     def map[B](f: A => B): Yoneda[F,B] = new Yoneda[F,B] { //纯粹的函数组合 map fusion
24         def apply[C](g: B => C): F[C] = yo( f andThen g)
25     }
26 }
27 trait Coyoneda[F[_],A] { coyo =>
28  type I
29  def fi: F[I]
100  def k(i: I): A
31  def run(implicit F: Functor[F]): F[A] =  //Coyoneda转F须要F Functor实例
32    F.map(fi)(k)
33  def toYoneda(implicit F: Functor[F]): Yoneda[F,A] = new Yoneda[F,A] { //转Yoneda须要Functor
34      def apply[B](f: A => B): F[B] = F.map(fi)(k _ andThen f)
35  }
36  def map[B](f: A => B): Coyoneda[F,B] = new Coyoneda[F,B] {
37      type I = coyo.I
38      def fi = coyo.fi
39      def k(i: I) = f(coyo k i)
40  }
41 }
42 object Yoneda {
43     def apply[F[_]: Functor,A](fa: F[A]) = new Yoneda[F,A] { //F转Yoneda须要Functor
44         def apply[B](f: A => B): F[B] = Functor[F].map(fa)(f)
45     }
46     implicit def yonedaFunctor[F[_]] = new Functor[({type l[x] = Yoneda[F,x]})#l] {
47         def map[A,B](ya: Yoneda[F,A])(f: A => B) = ya map f
48         
49     }
100 }
51 object Coyoneda {
52     def apply[F[_],A](fa: F[A]): Coyoneda[F,A] = new Coyoneda[F,A] {
53         type I = A          //把F[A]升格成Coyoneda, F并非为Functor
54         def fi = fa
55         def k(a: A) = a
56     }
57     implicit def coyonedaFunctor[F[_]] = new Functor[({type l[x] = Coyoneda[F,x]})#l] {
58         def map[A,B](ca: Coyoneda[F,A])(f: A => B) = ca map f   //Coyoneda一种就是Functor
59     }
100 }

亲戚亲戚朋友的目的是把任何F[A]变成Free Monad,这样亲戚亲戚朋友就须要有有2个多 用Coyoneda产生的Free:

Interpreter沿用了foldMap要怎样让调整了转换源目标类型 Functor >>> Coyoneda。其它如Trampoline机制维持不变。

Yoneda lemma是那我推论的:不可能 亲戚亲戚朋友有个那我的函数定义:def map[B](f: A => B): F[B],那亲戚亲戚朋友就肯定能得出F[A]值,不可能 亲戚亲戚朋友只须要把有2个多 恒等函数当作f就能得到F[A]。反过来推论:不可能 亲戚亲戚朋友有个F[A],F是任何Functor,A是任何类型,亲戚亲戚朋友同样可不须要得出以上的map函数。亲戚亲戚朋友可不须要用个类型来表示:

不可能 Coyoneda[S,A]是个多层嵌入类型。亲戚亲戚朋友在liftFU函数中须要借用scalaz的Unapply类型来分解出Coyoneda, S[A]要怎样让施用在liftF;

以上值得注意的是:F[A]可不须要直接升格等于Coyoneda,而Coyoneda是个Functor。换句话说亲戚亲戚朋友把F[A]升格到Coyoneda就可不须要当Functor来用了。

现在的问题 是不可能 能有个哪此土措施把F[A]变成Functor,就像Free Monad那样有个Free Functor就好了。范畴学中Yoneda lemma结论中的Coyoneda就是有2个多 Free Functor。

现在亲戚亲戚朋友可不须要把任何F[A]类型变成Free Monad并用它实现Monadic programming及副作用解译运算!

亲戚亲戚朋友想用Free Monad把Console[A]变成Monad: Free[Console,A],但亲戚亲戚朋友须要先得到Console的Functor实例:

1 implicit val consoleFunctor = new Functor[Console] {
2     def map[A,B](ca: Console[A])(f: A => B): Console[B] = ca match {
3         case GetLine => ?????
4         case PutLine(l) => ????
5     }
6 }