繁体   English   中英

如何将Free monads转换为Free appativeatives

[英]How to convert Free monads to Free applicatives

我正在使用cats库,并希望将Free Monad转换为Free Appativeative。

Free monads中有很多代码。但是,现在应用程序的某些部分必须并行运行。 有选择使用Tagless或Frees.io而不是Free的选项。但这将是一个巨大的变化...

这是一个示例DSL:

sealed trait DSLAction[A]

case class GetCustomer(request: Boolean) extends DSLAction[String]

case class GetSize(request: Boolean) extends DSLAction[Int]

val f1: Free[DSLAction, String] = liftF(GetCustomer(true))
val f2: Free[DSLAction, Int] = liftF(GetSize(true))
val f3: Free[DSLAction, Int] = liftF(GetSize(false))

  val interpreter: DSLAction ~> Id = {
    λ[DSLAction ~> Id] {
      case GetCustomer(_: Boolean) => {
        "hello"
      }
      case GetSize(_: Boolean) => {
        123
      }
    }
  }

Cats库提供了一种使用.monad()将FreeApplicative转换为Free monad的方法

但是,我想将Free转换为FreeApplicative以用于理解

我想定义一个方法toApplicative()完成工作...

type FEF[A] = FreeApplicative[DSLAction, A]

val f1AP: FEF[String] = toApplicative(f1)
val f2AP: FEF[Int] = toApplicative(f2)


val prog = for {
    a <- (f1AP, f2AP).mapN { case (l, r) => l + r }.monad
    b <- f3
  } yield {
    (a, b)
  }


  prog.foldMap(interpreter)

我确实尝试实现一些东西。但是不确定如何定义flatMap和tailRec方法。

否则可能会有另一种方式

  implicit val myConvertor = new Monad[FEF] {

    override def pure[A](x: A): FEF[A] = FreeApplicative.pure[DSLAction,A](x)

    override def flatMap[A, B](fa: FEF[A])(f: A => FEF[B]): FEF[B] = ???

    override def tailRecM[A, B](a: A)(f: A => FEF[Either[A, B]]): FEF[B] = ???
  }


  final def toApplicative[F, A](free: Free[DSLAction, A]) =
    free.foldMap[FreeApplicative[DSLAction, ?]] {
      λ[FunctionK[DSLAction, FEF]](fa => FreeApplicative.lift(fa))
    }

谢谢

尝试

 
 
 
  
  implicit val myConvertor = new Monad[FEF] { override def pure[A](x: A): FEF[A] = FreeApplicative.pure[DSLAction,A](x) override def flatMap[A, B](fa: FEF[A])(f: A => FEF[B]): FEF[B] = toApplicative(Monad[Free[DSLAction, ?]].flatMap(fa.monad)(a => f(a).monad)) override def tailRecM[A, B](a: A)(f: A => FEF[Either[A, B]]): FEF[B] = toApplicative(Monad[Free[DSLAction, ?]].tailRecM(a)(a => f(a).monad)) }
 
  

实际上toApplicative无效,因为它需要Monad[FreeApplicative[DSLAction,?]]并且这种实例不存在, FreeApplicative[DSLAction,?]Applicative ,而不是Monad (相反, FreeApplicative#monad可以工作,因为存在Monad[Free[DSLAction,?]] )。

https://typelevel.org/cats/datatypes/freeapplicative.html#differences-from-free

到目前为止,我们一直在做的一切与Free并没有太大的不同-我们已经建立了一个代数并对其进行了解释。 然而,有一些事情FreeApplicative可以做到Free不了。

因此,我猜有从FreeApplicative[DSLAction,?]Free[DSLAction,?]转换,但是没有从Free[DSLAction,?]FreeApplicative[DSLAction,?] 通常,您不能从可以做得更多的事情( Free只能做连续的执行)中获得可以做更多的事情( FreeApplicative可以并行执行和连续执行)。

FreeMonad ,因此它是一个Applicative但是此Applicative实例不同于FreeApplicativeApplicative实例。

引用@BogdanVakulenko在reddit上的链接

在一般情况下,将monad变成应用程序是绝对不可能的,因为许多应用程序(例如Const[M: Monoid] )都不构成monads。 如果您的monad保留了应用运算和monadic运算之间的区别,那么它将不再免费

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM