私が達成したいのは、シリアライズ可能で構成可能なプロセス記述子です。基本的に、いくつかのプリミティブProcessor
(シリアル化可能) を作成し、それらをより高次の s に構成できるようにしたいと考えProcessor
ています。その後、すべてが自動的にシリアル化可能のままになるはずです。これが私の現在の実装ですが、いくつかの猫の型クラス/データ構造でこれを行うよりエレガントな方法があると思います。Free、Kleisli、State などの強力なツールを利用する方法が思い浮かばないのは馬鹿げています。私の課題は、状態のタイプ、つまり のデータ フィールドDataWithContext
が変化し続けることでした。
でも、それを乗り越える方法があるはずですよね?
object Test {
import cats.implicits._
import cats.data.XorT
import scala.concurrent.Future
type Cause = String
case class DataWithContext[+A](data: A, context: List[String]) //context never need to change
trait Processor[-A, B] extends Serializable {
def process: DataWithContext[A] ⇒ XorT[Future, Cause, B]
}
implicit class ProcessorOps[A, B](self: Processor[A, B]) {
def >>[C](that: Processor[B, C]) = Con(self, that)
def zip[C](that: Processor[A, C]) = Zip(self, that)
}
//concat two processors
case class Con[A, B, C](a: Processor[A, C], b: Processor[C, B]) extends Processor[A, B] {
def process: DataWithContext[A] ⇒ XorT[Future, Cause, B] = (pc: DataWithContext[A]) ⇒
a.process(pc).flatMap { c ⇒
b.process(pc.copy(data = c))
}
}
//zip two processors
case class Zip[A, B, C](p1: Processor[A, B], p2: Processor[A, C])
extends Processor[A, (B, C)] {
def process: DataWithContext[A] ⇒ XorT[Future, Cause, (B, C)] =
(pc: DataWithContext[A]) ⇒
for {
b ← p1.process(pc)
c ← p2.process(pc)
} yield (b, c)
}
//an example of a primitive Processor
case object Count extends Processor[String, Int] {
def process: DataWithContext[String] ⇒ XorT[Future, Cause, Int] =
(dc: DataWithContext[String]) =>
XorT.pure[Future, Cause, Int](dc.data.length)
}
}