[英]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
可以并行执行和连续执行)。
Free
是Monad
,因此它是一个Applicative
但是此Applicative
实例不同于FreeApplicative
的Applicative
实例。
引用@BogdanVakulenko在reddit上的链接
在一般情况下,将monad变成应用程序是绝对不可能的,因为许多应用程序(例如
Const[M: Monoid]
)都不构成monads。 如果您的monad保留了应用运算和monadic运算之间的区别,那么它将不再免费
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.