在“Scala 中的 FP”一书中,有这种使用 ADT S
作为抽象指令集的方法,例如
sealed trait Console[_]
case class PrintLine(msg: String) extends Console[Unit]
case object ReadLine extends Console[String]
并用 Free[S, A]
组合它们,其中 S
稍后将被转换为 IO monad。
这可以用 Scalaz 的 Free
类型来完成吗?似乎所有 run
方法都需要 S
的仿函数实例。
最佳答案
是的,您需要一个仿函数,但您可以使用 Coyoneda
创建一个仿函数。
Coyoneda
会将任何 F[A]
变成 Coyoneda[F,A]
和 Coyoneda[F,A]
是一个仿函数。
scala> type ConsoleCoyo[A] = Coyoneda[Console, A]
defined type alias ConsoleCoyo
那么 scalaz 的 Free 有一个类型别名就是为了这个:
/** A free monad over the free functor generated by `S` */
type FreeC[S[_], A] = Free[({type f[x] = Coyoneda[S, x]})#f, A]
所以现在我们有一个免费的控制台单子(monad):
scala> type ConsoleMonad[A] = Free.FreeC[ConsoleCoyo,A]
defined type alias ConsoleMonad
您还会发现 scalaz 的 Free 具有将 F[A] 直接提升到 monad 的功能,这很方便:
/** A free monad over a free functor of `S`. */
def liftFC[S[_], A](s: S[A]): FreeC[S, A] =
liftFU(Coyoneda lift s)
所以,例如:
scala> Free.liftFC(ReadLine)
res1: scalaz.Free.FreeC[Console,String] = Suspend(scalaz.Coyoneda$$anon$22@360bb132)
关于scala - 在 Scalaz 中将 Free 与非仿函数一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25403944/