Скала кошки неоднозначные скрытые ценности
import cats._
import cats.implicits._
trait Console[F[_]]{
def readInput() : F[Int]
def print(msg: String) : F[Unit]
}
class Foo {
def doFoo[F[_]: Monad](number: Int)(implicit C: Console[F]) : F[Unit] = {
C.readInput().flatMap{input =>
if (input == number) C.print("you won").map(_ => ())
else if (input > number) C.print("you guessed too high").flatMap(_ => doFoo(number))
else C.print("you guessed too low").flatMap(_ => doFoo(number))
}
}
}
Но я получаю эту загадочную ошибку от компилятора
cmd18.sc:5: ambiguous implicit values:
both value catsStdInstancesForList in trait ListInstances of type => cats.Traverse[List] with cats.Alternative[List] with cats.Monad[List] with cats.CoflatMap[List]
and value catsStdInstancesForVector in trait VectorInstances of type => cats.Traverse[Vector] with cats.Monad[Vector] with cats.Alternative[Vector] with cats.CoflatMap[Vector]
match expected type cats.Monad[F]
else if (input > number) C.print("you guessed too high").flatMap(_ => dooFoo(number))
^
1 ответ
Проблема в том, что вы слишком много спрашиваете о типах Scala. Он пытается выяснить параметр типа, который ему нужен для doFoo[?](number)
и хотя нам, людям, совершенно ясно, что это должно быть F
учитывая контекст выражения doFoo(number)
появляется в, компилятор не так умен.
Самое простое решение - просто явно указать параметр типа:
.flatMap(_ => doFoo[F](number))
Если вас это раздражает, вы можете немного помочь компилятору, отладив F[_]: Monad
ограничение, так что вы можете сделать заказ из Console
а также Monad
случаи явные:
import cats._
import cats.implicits._
trait Console[F[_]]{
def readInput() : F[Int]
def print(msg: String) : F[Unit]
}
class Foo {
def doFoo[F[_]](number: Int)(implicit C: Console[F], F: Monad[F]) : F[Unit] = {
C.readInput().flatMap{input =>
if (input == number) C.print("you won").map(_ => ())
else if (input > number) C.print("you guessed too high").flatMap(_ => doFoo(number))
else C.print("you guessed too low").flatMap(_ => doFoo(number))
}
}
}
В вашей оригинальной версии Monad
привязка к контексту становилась неугодной неявной Monad[F]
параметр, который был раньше C: Console[F]
в списке неявных параметров, и поэтому компилятор сначала пытался разрешить его. В вышеприведенной версии без сахара я изменил порядок, чтобы он Console[F]
во-первых, что заставит все работать нормально, когда компилятор попытается сделать вывод F
для doFoo(number)
звонки.