Я пытаюсь узнать, как использовать FreeMonads для внедрения интерпретаторов для моих сервисов.Как связать действие и интерпретировать их вместе с Scalaz?
Пусть у меня есть
sealed trait ServiceAction[T] extends Product with Serializable
case class ConsumeCommand(cmd: AccruePoints) extends ServiceAction[AccruePointModel]
case class CreateEvent(evt: PointsAccruedEvent) extends ServiceAction[PointsAccruedEvent]
sealed trait LogAction[T] extends Product with Serializable
case class Info(msg: String) extends LogAction[Unit]
case class Error(msg: String) extends LogAction[Unit]
и монаду действия
type LogActionF[A] = Free[LogAction, A]
type ServiceActionF[A] = Free[ServiceAction, A]
Далее, я определяю свою службу, как это:
trait PointAccrualService {
def consume(cmd: AccruePoints): ServiceActionF[AccruePointModel] = Free.liftF(ConsumeCommand(cmd))
def emit(evt: PointsAccruedEvent) : ServiceActionF[PointsAccruedEvent] = Free.liftF(CreateEvent(evt))
}
и
trait LogService {
def info(msg: String) : LogActionF[Unit] = Free.liftF(Info(msg))
def error(msg: String) : LogActionF[Unit] = Free.liftF(Error(msg))
}
с объектом каждого
object LogService extends LogService
object PointAccrualService extends PointAccrualService
Мой LogServiceInterpreter
как это:
case class LogServiceConsoleInterpreter() extends LogServiceInterpreter {
def apply[A](action: LogActionF[A]): Task[A] = action.foldMap(handler)
protected def handler = new (LogAction ~> Task) {
override def apply[A](fa: LogAction[A]) = fa match {
case Info(m) =>
now(info(m))
case Error(m) =>
now(error(m))
}
}
def info(msg: String): Unit = {
println(s"INFO: $msg")
}
def error(msg: String): Unit = {
println(s"ERROR: $msg")
}
}
Точно так же, мой PointAccuralServiceInterpreter
, как это:
case class PointAccuralServiceInterpreter() {
def apply[A] (action: ServiceActionF[A]) : Task[A] = action.foldMap(handler)
protected def handler = new (ServiceAction ~> Task) {
override def apply[A](fa: ServiceAction[A]): Task[A] = fa match {
case ConsumeCommand(cmd) => {
println("Service ConsumeCommand:" + cmd)
now(cmd)
}
case CreateEvent(evt) => {
println("Service CreateEvent:" + evt)
now(evt)
}
}
}
}
Моя логика проста, я хочу для регистрации и использования моей команды, а затем создания события, похожего на источник событий:
val ret = for {
_ <- logService.info("Command: " + cmd)
model <- service.consume(cmd)
_ <- logService.info("Model: " + model)
evt <- service.emit(model.toEvent("200", "Event Sent"))
_ <- logService.info("Event:" + evt)
} yield evt
Этот код даже не компилируется на самом деле.
Что мне делать? Я думаю, что я должен использовать Coproduct, чтобы связать их и выполнить эту логику, кормив моего переводчика.
я нашел что-то здесь https://groups.google.com/forum/#!topic/scalaz/sHxFsFpE86c
или он сказал, что я могу использовать бесформенные сделать так Folding a list of different types using Shapeless in Scala
Они все слишком сложно. Все, что я хочу, после того, как я определяю свою логику, как ее выполнить?
Надеюсь, что я приведу здесь достаточно подробностей для ответа. Я действительно хочу это узнать. Спасибо
Ваш вопрос не понятен вообще. – pedrofurla
Извините, позвольте мне добавить еще код. Я бросился на обед с другими людьми.Я должен был положить больше в тело – sowen