W książce "FP in Scala" jest to podejście do używania ADT S
jako abstrakcyjny zestaw instrukcji
sealed trait Console[_]
case class PrintLine(msg: String) extends Console[Unit]
case object ReadLine extends Console[String]
i komponowanie ich za pomocą Free[S, A]
gdzie S
zostałaby później przetłumaczona na monadę IO. Czy można to zrobić z Scalazem Free
rodzaj? Wydaje się, że wszystko run
metody wymagają instancji funktora dla S
.
Odpowiedzi:
9 dla odpowiedzi № 1tak, potrzebujesz funktora, ale możesz go utworzyć używając Coyoneda
.
Coyoneda
zmieni każdy F[A]
do a Coyoneda[F,A]
i Coyoneda[F,A]
jest funktorem.
scala> type ConsoleCoyo[A] = Coyoneda[Console, A]
defined type alias ConsoleCoyo
Następnie skalaz "s Free ma alias typu właśnie dla tego:
/** A free monad over the free functor generated by `S` */
type FreeC[S[_], A] = Free[({type f[x] = Coyoneda[S, x]})#f, A]
Więc teraz mamy darmową monadę na konsolę:
scala> type ConsoleMonad[A] = Free.FreeC[ConsoleCoyo,A]
defined type alias ConsoleMonad
również znajdziesz poręczny, że darmowy skalak ma funkcję podnoszenia F [A] bezpośrednio do monady:
/** A free monad over a free functor of `S`. */
def liftFC[S[_], A](s: S[A]): FreeC[S, A] =
liftFU(Coyoneda lift s)
więc na przykład:
scala> Free.liftFC(ReadLine)
res1: scalaz.Free.FreeC[Console,String] = Suspend(scalaz.Coyoneda$$anon$22@360bb132)