5

これはおそらく以前に何度も尋ねられたことがありますが、私が見つけた提案はどれも役に立ちませんでした.

いくつかの副作用に依存する長い数値を生成する単純な Scala コードがあります。私は IO モナドでラップしていますが、最小電力の原則に従って、実際には自分の関数を として宣言しています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)

また、コードを改善するための提案があれば、お知らせください。

4

1 に答える 1

8

問題は、コンテキストがF[_]: Effectdesugar で暗黙的なパラメーターにバインドされるため、コンパイラーは次のように表示されることです。

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

つまり、メソッドの本体で暗黙的なものを解決しようとするたびに、明示的なものとこの合成のものがあいまいであるEffect[F]と見なされるため、失敗します。Fev

解決策は、コンテキスト バインドまたは明示的暗黙F: Effect[F]パラメーターのいずれかを削除することです。Scala ではこの 2 つを組み合わせることができるという事実が、この種のエラーを起こしやすい理由の 1 つであるため、コンテキスト バウンドを無効にすることをお勧めします (私の見解では、言語設計者による深刻な判断ミスでした。前に何度も言った)。

于 2019-02-18T07:49:27.473 に答える