【问题标题】:Make F[_] implementing Monad trait while accepting IO让 F[_] 在接受 IO 的同时实现 Monad trait
【发布时间】: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 不是 MonadListEitherOption 或您可能认为的任何其他数据类型也不是。它们都形成Monad(另一种说法是它们有一个与之关联的Monad 实例)。这是 typeclass 和传统 subtyping 之间的主要区别之一,理解这一点很重要,因此您可以了解为什么 F[_] : Monad 有效而 F[_] &lt;: Monad 无效. - 顺便说一句,如果您删除糖语法,这更容易看到:class External[_](implicit ev1: Monad[F], ev2: Concurrent[F]); PS:Concurrent IS A Monad 因此你只需要那个
  • 另外,如果您对这一切还很陌生,我建议您先坚持使用具体的 IO 一段时间,然后再深入了解通常所说的 “无标签决赛”无论如何,请随意加入 typelevel discord 服务器,在那里您可能会寻求有关这种风格的更多指导。
  • @LuisMiguelMejíaSuárez 正确的介词在stackoverflow.com/questions/68477132 中讨论过 :)

标签: scala typeclass implicit scala-cats cats-effect


【解决方案1】:

替换

class External[F[_] <: Monad[F] : Concurrent]

class External[F[_]: Monad : Concurrent]

成为Monad 并不意味着成为Monad 的子类型。这意味着当前类型存在类型类Monad 的实例。

与 OOP 不同,在 FP 中实现一些抽象行为不是通过扩展/继承/子类型多态性而是通过隐式/定义类型类实例/ad hoc 多态性来实现的。

也许你需要导入必要的语法:

import cats.syntax.flatMap._

import cats.syntax.functor._

或同时使用所有的语法

import cats.syntax.all._

How to enforce F[_] to be an instance of Monad

https://eed3si9n.com/herding-cats/import-guide.html

【讨论】:

  • 不够,从那时起proxy.get() 将没有Monad 特征。
  • @scala-n00b 也许你需要导入语法stackoverflow.com/questions/58150448/…
  • @scala-n00b 不,这正是因为导入语法。 scastie.scala-lang.org/DmytroMitin/UjF8GBFRTlqF3ZHiO2eTOw/1 只是 Functor 语法,而不是 FlatMap 语法。
  • @scala-n00b 通常比 import cats.syntax.all._ 更好,因为这样您将获得所有语法,并且您不需要关心层次结构的哪一部分提供了它。
  • @DmytroMitin 同意,我认为我之前的评论在某处缺少 "beginners" :)
猜你喜欢
  • 2011-10-02
  • 2019-08-09
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多