我想要实现的是可序列化和可组合的进程描述符。基本上我将创建一些原始Processor
(可序列化),然后我希望能够将它们组合成更高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)
}
}