我正在使用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))
}
谢谢
答案 0 :(得分:0)
尝试
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,?]
的转换。通常,您不能从功能较少的事情(FreeApplicative
仅可以连续执行)中获得更多可以做的事情(Free
可以并行执行和连续执行)。
Free
是Monad
,因此它是Applicative
,但是此Applicative
实例与Applicative
实例是FreeApplicative
实例不同
@bogdanVakulenko在reddit的链接中的引言
将单子变成应用中的应用程序确实是不可能的 一般情况,因为许多应用程序(例如
Const[M: Monoid]
)不 形成单子。如果您的单子保留了两者之间的区别 应用操作和单子操作,那么它就不再免费