2

根据这篇用 Haskell 编写的博客文章,我正在尝试在 Scala 中实现一个无标签的最终 DSL 和解释器。

我可以运行一个示例 - 请参见下面的代码,但我不太明白我为什么需要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)

有没有一种简单的方法来消除其中一个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)
    }
}
4

1 回答 1

2

语法

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使用:implicitlyF: 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.
于 2019-01-13T10:44:50.103 回答