【问题标题】:value flatMap is not a member of type parameter F[Long] when using cats.effect使用cats.effect时,值flatMap不是类型参数F[Long]的成员
【发布时间】:2019-07-11 10:27:41
【问题描述】:

这可能以前被问过很多次,但我找到的建议都没有帮助。

我有一个简单的 Scala 代码,它会生成取决于某些副作用的长数字。我将东西包装在一个 IO monad 中,但根据最小功率原则,我实际上将我的函数声明为 F[_]: Effect。现在代码无法编译,我不明白为什么,请提出可能有问题的地方

import cats.effect.{Clock, Effect}
import cats.syntax.all._
import java.util.concurrent.TimeUnit


...

  def generateId[F[_]: Effect](rid: Long)(implicit F: Effect[F], clock: Clock[F]): F[Long] =
    for {
      currentTimeNanos <- clock.realTime(TimeUnit.NANOSECONDS)
      tid              <- F.delay(Thread.currentThread().getId)
    } yield
      (tid << 40 /*    */ & 0xFFFFFF0000000000L) |
        (rid << 16 /*  */ & 0x000000FFFFFF0000L) |
        (currentTimeNanos & 0x000000000000FFFFL)

[error] /.../package.scala:34:41: value flatMap is not a member of type parameter F[Long]
[error]       currentTimeNanos <- clock.realTime(TimeUnit.NANOSECONDS)
[error]                                         ^
[error] /.../package.scala:35:34: value map is not a member of type parameter F[Long]
[error]       tid              <- F.delay(Thread.currentThread().getId)

另外,如果您对改进代码有任何建议,请告诉我。

【问题讨论】:

    标签: scala scala-cats cats-effect


    【解决方案1】:

    问题是F[_]: Effect 中的上下文绑定到一个隐式参数中,所以编译器看到的是这样的:

    def generateId[F[_]](rid: Long)(implicit ev: Effect[F], F: Effect[F], ...): F[Long] = ...
    

    这意味着每次尝试解析方法主体中的隐式 Effect[F] 时,它都会失败,因为它认为显式 F 和合成的 ev 不明确。

    解决方案是删除上下文绑定或显式隐式F: Effect[F] 参数。我建议取消上下文绑定,因为 Scala 允许您将两者结合起来是很容易犯这种错误的部分原因(在我看来,这是语言设计者的严重误判,因为我已经said many times before)。

    【讨论】:

    • 仅作记录,如果我要使用上下文绑定,我应该如何获得对“糖化”隐式参数的引用?我最终得到了implicitly[Effect[F]]。这是正确的方法吗?
    • @edio 是的,完全正确,或者直接写Effect[F],相当于。
    • 谢谢!那个鬼鬼祟祟的apply...我不知道有人可以这样称呼通用apply :)
    • @edio 是的,这是一个不错的技巧,也是一个相当常见的习语,即使在标准库中也能找到(例如,试试Ordering[Int])。
    猜你喜欢
    • 2023-03-17
    • 2013-05-05
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    相关资源
    最近更新 更多