【发布时间】:2021-12-10 04:15:34
【问题描述】:
假设我们有代码(<: Monad[F] 无法按预期工作):
class External[F[_] <: Monad[F] : Concurrent](implicit proxy: Proxy[F]) { ... }
class Proxy[F[_] <: Monad[F]](implicit storage: Storage, async: Async[F]) {
def get(key: String): F[Option[Entry]] = {
async.blocking(storage.get(key))
}
}
我希望F[_] 成为Monad,以便proxy.get() 具有这些特征并启用例如(在External 类中):
proxy.get(key).flatMap(...)
到目前为止一切顺利,但是当尝试使用 cats.effect.IO 实例化时,它不适用于 External:
implicit val proxy: Proxy[IO] = new Proxy()
implicit val external: External[IO] = new External()
有错误输出:
inferred type arguments [[+A]cats.effect.IO[A]] do not conform to value <local External>'s type parameter bounds [F[_] <: cats.Monad[F]]
如何解决或以不同的方式实现?
【问题讨论】:
-
IO不是Monad,List、Either、Option或您可能认为的任何其他数据类型也不是。它们都形成Monad(另一种说法是它们有一个与之关联的Monad实例)。这是 typeclass 和传统 subtyping 之间的主要区别之一,理解这一点很重要,因此您可以了解为什么F[_] : Monad有效而F[_] <: Monad无效. - 顺便说一句,如果您删除糖语法,这更容易看到:class External[_](implicit ev1: Monad[F], ev2: Concurrent[F]); PS:ConcurrentIS AMonad因此你只需要那个 -
另外,如果您对这一切还很陌生,我建议您先坚持使用具体的
IO一段时间,然后再深入了解通常所说的 “无标签决赛”无论如何,请随意加入 typelevel discord 服务器,在那里您可能会寻求有关这种风格的更多指导。 -
@LuisMiguelMejíaSuárez 正确的介词在stackoverflow.com/questions/68477132 中讨论过 :)
标签: scala typeclass implicit scala-cats cats-effect