2017-08-30 49 views
0

我正在與Scala和doobie合作。我試圖實現一個交易者特徵,可以通過MacWire注入並用於不同的任務/未來單元(例如用於測試)。Scala(doobie):類型不變

import doobie.imports 
import doobie.imports._ 
import fs2.Task 
import fs2.util.{Catchable, Suspendable} 

trait Transactor[M[_]] { 
    implicit def catchable: Catchable[M] = implicitly 
    val transactor: M[imports.Transactor[M]] 
    def transact[A](q: ConnectionIO[A]): M[A] = catchable.flatMap(transactor)(xa => q.transact(xa)) 
} 

case class H2Transactor[M[_]: Catchable: Suspendable](pure: PureConfig) extends Transactor[M] { 
    override val transactor = doobie.h2.imports.H2Transactor[M](
    pure.config.persistence.name, 
    pure.config.persistence.user.orNull, 
    pure.config.persistence.password.orNull 
) 
} 

... 
trait DatabaseModule { lazy val transactor = wire[H2Transactor[Task]] } 
trait TestModule { lazy val transactor = wire[H2Transactor[IOLite]] } 

但我得到這個錯誤:

[error] .../src/main/scala/.../persistence/transactor/H2Transactor.scala:13: type mismatch; 
[error] found : M[doobie.h2.h2transactor.H2Transactor[M]] 
[error] required: M[doobie.imports.Transactor[M]] 
[error]  (which expands to) M[doobie.util.transactor.Transactor[M]] 
[error] Note: doobie.h2.h2transactor.H2Transactor[M] <: doobie.imports.Transactor[M], but type M is invariant in type _. 
[error] You may wish to define _ as +_ instead. (SLS 4.5) 

它爲Task,因爲它被定義爲Task[+A],但doobie的IOLiteIOLite[A]。任何方式,我可以使這項工作?或者我使用不同的Monad類型而不是Task(不能更改IOLite是doobie測試所必需的)?

回答

2

試一下:

override val transactor = doobie.h2.imports.H2Transactor[M](...).widen 

widen是,如果MFunctor實例可用的操作(在catsscalaz)。它允許你把M[A]當作M[B]如果AB的子類

+0

謝謝。這有助於:'覆蓋val交易者:M [imports.Transactor [M]] = Functor [M] .widen [doobie.h2.imports.H2Transactor [M],imports.Transactor [M]](doobie.h2.imports。 H2Transactor [M](...))' –