代码之家  ›  专栏  ›  技术社区  ›  jon hanson

Scala中无标记的最后一个示例需要多余的第二个interp arg

  •  2
  • jon hanson  · 技术社区  · 6 年前

    我正在尝试实现一个无标签的最终DSL&Scala中的解释器,基于 this 用Haskell写的博客文章。

    我可以运行一个示例—请参阅下面的代码,但我不太明白为什么需要 testVal(Interp)(Interp) . 如果我只提供一个 Interp 参数,则会出现以下编译错误:

    Error:(29, 24) could not find implicit value for evidence parameter of type Test.Expr[Test.Id]
            val x = testVal(Interp)
    Error:(29, 24) not enough arguments for method testVal: (implicit evidence$1: Test.Expr[Test.Id])Test.Id[Int].
    Unspecified value parameter evidence$1.
            val x = testVal(Interp)
    

    有没有一种简单的方法可以消除 内页

    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: Expr[F]): F[Int] =
            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) -- won't compile
            val x = testVal(Interp)(Interp)
            println(x)
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Andrey Tyukin    6 年前

    语法

    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.
    
    推荐文章