在Scalaz中将Free与非函子一起使用
在《Scala中的FP》一书中,有这样一种使用ADT在Scalaz中将Free与非函子一起使用,scala,design-patterns,functional-programming,scalaz,algebraic-data-types,Scala,Design Patterns,Functional Programming,Scalaz,Algebraic Data Types,在《Scala中的FP》一书中,有这样一种使用ADTs作为抽象指令集的方法,如 sealed trait Console[_] case class PrintLine(msg: String) extends Console[Unit] case object ReadLine extends Console[String] 然后用一个Free[S,a]组合它们,其中S稍后将被转换为IO单子。 这可以用Scalaz的Free类型完成吗?似乎所有的run方法都需要S的functor实例是的,您
s
作为抽象指令集的方法,如
sealed trait Console[_]
case class PrintLine(msg: String) extends Console[Unit]
case object ReadLine extends Console[String]
然后用一个Free[S,a]
组合它们,其中S
稍后将被转换为IO单子。
这可以用Scalaz的
Free
类型完成吗?似乎所有的run
方法都需要S
的functor实例是的,您需要一个functor,但是您可以使用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]直接提升到单子的功能:
/** 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)
注意:
FreeC
已经Coyoneda
是它的第一个参数,所以你只需要FreeC[Console,A]
,而不是FreeC[ConsoleCoyo,A]
。