日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Scalaz(32)- Free :lift - Monad生产线

發(fā)布時(shí)間:2025/5/22 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scalaz(32)- Free :lift - Monad生产线 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

??? 在前面的討論里我們提到自由數(shù)據(jù)結(jié)構(gòu)就是產(chǎn)生某種類型的最簡(jiǎn)化結(jié)構(gòu),比如:free monoid, free monad, free category等等。我們也證明了List[A]是個(gè)free monoid。我們?cè)倏纯磃ree monad結(jié)構(gòu)Free的定義:scalaz/Free.scala

?

/** A free operational monad for some functor `S`. Binding is done using the heap instead of the stack,* allowing tail-call elimination. */ sealed abstract class Free[S[_], A] { .../** Return from the computation with the given value. */private[scalaz] case class Return[S[_], A](a: A) extends Free[S, A]/** Suspend the computation with the given suspension. */private[scalaz] case class Suspend[S[_], A](a: S[Free[S, A]]) extends Free[S, A] ...

?

我們?cè)谏弦黄镒C明過(guò)Free就是free monad,因?yàn)镕ree是個(gè)Monad而且它的結(jié)構(gòu)是最簡(jiǎn)單的了:

1、Free[S[_],A]可以代表一個(gè)運(yùn)算

2、case class Return是一個(gè)數(shù)據(jù)結(jié)構(gòu)。Return(a:A)代表運(yùn)算結(jié)束,運(yùn)算結(jié)果a存放在結(jié)構(gòu)中。另一個(gè)意義就是Monad.point(a:A),把一個(gè)任意A值a升格成Free

3、case class Suspend也是另一個(gè)數(shù)據(jù)結(jié)構(gòu)。Suspend(a: S[Free[S,A]])代表把下一個(gè)運(yùn)算存放在結(jié)構(gòu)中。如果用Monad.join(a: F[F[A]])表示,那么里面的F[A]應(yīng)該是個(gè)Free[S,A],這樣我們才可能把運(yùn)算結(jié)束結(jié)構(gòu)Return[S,A](a:A)存放到Suspend中來(lái)代表下一步結(jié)束運(yùn)算。

注意,Suspend(a: S[Free[S,A]])是個(gè)遞歸類型,S必須是個(gè)Functor,但不是任何Functor,而是map over Free[S,A]的Functor,也就是運(yùn)算另一個(gè)Free[S,A]值。如果這個(gè)Free是Return則返回運(yùn)算結(jié)果,如果是Suspend則繼續(xù)遞歸運(yùn)算。

簡(jiǎn)單來(lái)說(shuō)Free是一個(gè)把Functor S[_]升格成Monad的產(chǎn)生器。我們可以用Free.liftF函數(shù)來(lái)把任何一個(gè)Functor升格成Monad??纯碏ree.liftF的函數(shù)款式就知道了:

/** Suspends a value within a functor in a single step. Monadic unit for a higher-order monad. */def liftF[S[_], A](value: => S[A])(implicit S: Functor[S]): Free[S, A] =Suspend(S.map(value)(Return[S, A]))

liftF可以把一個(gè)S[A]升格成Free[S,A]。我們用個(gè)例子來(lái)證明:

1 package Exercises 2 import scalaz._ 3 import Scalaz._ 4 import scala.language.higherKinds 5 import scala.language.implicitConversions 6 object freelift { 7 trait Config[+A] { 8 def get: A 9 } 10 object Config { 11 def apply[A](a: A): Config[A] = new Config[A] { def get = a} 12 implicit val configFunctor = new Functor[Config] { 13 def map[A,B](ca: Config[A])(f: A => B) = Config[B](f(ca.get)) 14 } 15 } 16 17 val freeConfig = Free.liftF(Config("hi config")) //> freeConfig : scalaz.Free[Exercises.freelift.Config,String] = Suspend(Exercises.freelift$Config$$anon$2@d70c109)

在上面的例子里Config是個(gè)運(yùn)算A值的Functor。我們可以用Free.liftF把Config(String)升格成Free[Config,String]。實(shí)際上我們可以把這個(gè)必須是Functor的門(mén)檻取消,因?yàn)橛肅oyoneda就可以把任何F[A]拆解成Coyoneda[F,A],而Coyoneda天生是個(gè)Functor。我們先看個(gè)無(wú)法實(shí)現(xiàn)map函數(shù)的F[A]:

1 trait Interact[+A] //Console交互 2 //println(prompt: String) then readLine 返回String 3 case class Ask(prompt: String) extends Interact[String] 4 //println(msg: String) 不反回任何值 5 case class Tell(msg: String) extends Interact[Unit]

由于Ask和Tell都不會(huì)返回泛類值,所以無(wú)需或者無(wú)法實(shí)現(xiàn)map函數(shù),Interact[A]是個(gè)不是Functor的高階類。我們必須把它轉(zhuǎn)成Coyoneda提供給Free產(chǎn)生Monad:

1 Free.liftFC(Tell("hello")) //> res0: scalaz.Free.FreeC[Exercises.freelift.Interact,Unit] = Suspend(scalaz.Coyoneda$$anon$22@71423665) 2 Free.liftFC(Ask("how are you")) //> res1: scalaz.Free.FreeC[Exercises.freelift.Interact,String] = Suspend(scalaz.Coyoneda$$anon$22@20398b7c)

我們看看liftFC函數(shù)定義:

/** A version of `liftF` that infers the nested type constructor. */def liftFU[MA](value: => MA)(implicit MA: Unapply[Functor, MA]): Free[MA.M, MA.A] =liftF(MA(value))(MA.TC)/** A free monad over a free functor of `S`. */def liftFC[S[_], A](s: S[A]): FreeC[S, A] =liftFU(Coyoneda lift s)

Coyoneda lift s 返回結(jié)果Coyoneda[S,A], liftFU用Unapply可以把Coyoneda[S,A]轉(zhuǎn)化成S[A]并提供給liftF??纯碪napply這段:

/**Unpack a value of type `M0[A0, B0]` into types `[a]M0[a, B0]` and `A`, given an instance of `TC` */implicit def unapplyMAB1[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[({type λ[α] = M0[α, B0]})#λ]): Unapply[TC, M0[A0, B0]] {type M[X] = M0[X, B0]type A = A0} = new Unapply[TC, M0[A0, B0]] {type M[X] = M0[X, B0]type A = A0def TC = TC0def leibniz = refl}/**Unpack a value of type `M0[A0, B0]` into types `[b]M0[A0, b]` and `B`, given an instance of `TC` */implicit def unapplyMAB2[TC[_[_]], M0[_, _], A0, B0](implicit TC0: TC[({type λ[α] = M0[A0, α]})#λ]): Unapply[TC, M0[A0, B0]] {type M[X] = M0[A0, X]type A = B0} = new Unapply[TC, M0[A0, B0]] {type M[X] = M0[A0, X]type A = B0def TC = TC0def leibniz = refl}

好了。但是又想了想,一個(gè)是Functor的Interact又是怎樣的呢?那Ask必須返回一個(gè)值,而這個(gè)值應(yīng)該是個(gè)Free,實(shí)際上是代表下一個(gè)運(yùn)算:

1 package Exercises 2 import scalaz._ 3 import Scalaz._ 4 import scala.language.higherKinds 5 object interact { 6 trait Interact[+A] 7 case class Ask[Next](prompt: String, n: String => Next) extends Interact[Next] 8 case class Tell[Next](msg: String, n: Next) extends Interact[Next] 9 10 object interFunctor extends Functor[Interact] { 11 def map[A,B](ia: Interact[A])(f: A => B): Interact[B] = ia match { 12 case Tell(m,n) => Tell(m, f(n)) 13 case g: Ask[A] => Ask[B](g.prompt, g.n andThen f) 14 } 15 }

所以Ask返回Next類型值,應(yīng)該是個(gè)Free,代表下一個(gè)運(yùn)算。

?

?

?

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/tiger-xc/p/5290667.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的Scalaz(32)- Free :lift - Monad生产线的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。