我已經爲使用免費monad的ETL過程實現了一種簡單的語言。當使用List
作爲數據讀取和存儲的輸入和輸出時,一切工作正常。不過我使用異步圖書館和Future[List]
如何在將來使用免費monad [M [_]]
常見的進口工作和定義
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats.free.Free
import cats.free.Free._
sealed trait Ops[A]
type OpsF[A] = Free[Ops, A]
與List
case class Fetch(offset: Int, amount: Int) extends Ops[List[Record]]
case class Store(recs: List[Record]) extends Ops[List[Response]]
def fetch(offset: Int, amount: Int): OpsF[List[Record]] =
liftF[Ops, List[Record]](Fetch(offset, amount))
def store(recs: List[Record]): OpsF[List[Response]] =
liftF[Ops, List[Response]](Store(recs))
def simpleEtl(offset: Int, amount: Int): Free[Ops, List[Response]] =
fetch(offset, amount).flatMap(r => store(r))
工作不Future[List]
case class Fetch(offset: Int, amount: Int) extends Ops[Future[List[Record]]]
case class Store(recs: List[Record]) extends Ops[Future[List[Response]]]
def fetch(offset: Int, amount: Int): OpsF[Future[List[Record]]] =
liftF[Ops, Future[List[Record]]](Fetch(offset, amount))
def store(recs: List[Record]): OpsF[Future[List[Response]]] =
liftF[Ops, Future[List[Response]]](Store(recs))
// explicit types in case I am misunderstanding more than I think
def simpleEtl(offset: Int, amount: Int): Free[Ops, Future[List[Response]]] =
fetch(offset, amount).flatMap { rf: Future[List[Record]] =>
val getResponses: OpsF[Future[List[Response]]] = rf map { r: List[Record] =>
store(r)
}
getResponses
}
工作如預期從...返回在flatMap
/map
是錯誤的 - 我沒有得到OpsF[Future]
但Future[OpsF]
Error:(34, 60) type mismatch;
found : scala.concurrent.Future[OpsF[scala.concurrent.Future[List[Response]]]]
(which expands to) scala.concurrent.Future[cats.free.Free[Ops,scala.concurrent.Future[List[String]]]]
required: OpsF[scala.concurrent.Future[List[Response]]]
(which expands to) cats.free.Free[Ops,scala.concurrent.Future[List[String]]]
val getResponses: OpsF[Future[List[Response]]] = rf map { r: List[Record] =>
我目前的解決方法是讓store
接受Future[List[Record]]
,並讓翻譯地圖上的Future
,但感覺笨拙。
該問題不是特定於List
- Option
也會有用。
我做錯了嗎?這是否有某種單體變壓器?
這似乎是一個monad變壓器的典型模式,第一次看起來像是Haskell有一個'FreeT',但是無法在Scalaz或貓中找到它。 –
從[7.2.0]開始,scalaz擁有'FreeT'(https://oss.sonatype.org/service/local/repositories/archive/org/scalaz/scalaz_2.11/7.2.0/scalaz_2.11-7.2的3.0 javadoc.jar /!/ index.html的#scalaz.FreeT)。 –
我可以指向47度的圖書館嗎?它恰當地命名爲http://47deg.github.io/fetch/,它很快將成爲一個類型級的孵化器?請注意,我沒有爲47度工作,但它似乎已經爲您想要做的大部分工作提供瞭解決方案。 – wheaties