Синтаксис
def f[X: Y](args: Types): Res = { ... }
является ярлыком для
def f[X](args: Types)(implicit yx: Y[X]): Res = { ... }
так что если вы напишите
def testVal[F[_]: Expr](f: Expr[F]): F[Int] = { ... }
тогда это так же, как если бы вы написали
def testVal[F[_]](f: Expr[F])(implicit redundant: Expr[F]): F[Int] = { ... }
но вам явно не нужно одно и то же Expr[F]
дважды.
Подпись должна быть либо
def testVal[F[_]: Expr]: F[Int]
или
def testVal[F[_]](implicit f: Expr[F]): F[Int]
но не оба одновременно.
Вот полный пример, который также показывает, как получить f
, используя implicitly
в случае, если вы решите использовать вариант F: Expr
(который не присваивает имя неявному аргументу):
import scala.language.higherKinds
object Test {
trait Expr[F[_]] {
def const(i: Int): F[Int]
def lam[A, B](f: F[A] => F[B]): F[A => B]
def app[A, B](f: F[A => B], a: F[A]): F[B]
def add(x: F[Int], y: F[Int]): F[Int]
}
type Id[A] = A
object Interp extends Expr[Id] {
override def const(i: Int): Id[Int] = i
override def lam[A, B](f: Id[A] => Id[B]): Id[A => B] = f
override def app[A, B](f: Id[A => B], a: Id[A]): Id[B] = f(a)
override def add(x: Id[Int], y: Id[Int]): Id[Int] = x + y
}
def testVal[F[_]: Expr]: F[Int] = {
implicit val f = implicitly[Expr[F]]
f.app(
f.lam[Int, Int](
x => f.add(x, f.const(1))),
f.const(10)
)
}
def main(args: Array[String]): Unit = {
val x = testVal(Interp)
println(x)
}
}
Более того, если вы сделаете Interp
самим неявным, тогда вы можете опустить все списки аргументов при вызове testVal
и вместо этого написать просто
val x = testVal // no arguments at all.