Классы типов в Scala

Имея опыт работы с Haskell, я в настоящее время пытаюсь познакомиться с Scala.

Я столкнулся с некоторыми проблемами при попытке перевести небольшой расширяемый язык выражений из Haskell в Scala. Основная проблема написания типа данных, расширяемого как новыми вариантами данных, так и операциями, широко известна как проблема выражения .

Мое исходное решение в Haskell использует классы типов и объявления экземпляров с ограничениями. База моего выражения определяется следующим образом:

module Expr where

class Expr e where
 eval :: e -> Integer

data Lit = Lit Integer
instance Expr Lit where
  eval (Lit l) = l

data Plus a b = (Expr a, Expr b) => Plus a b
instance (Expr a, Expr b) => Expr (Plus a b) where
  eval (Plus x y) = (eval x) + (eval y)

Затем у меня есть одно расширение данных, которое добавляет умножение:

module ExprWithMul where
import Expr

data Mul a b = (Expr a, Expr b) =>  Mul a b
instance (Expr a, Expr b) => Expr (Mul a b) where
  eval (Mul x y) = (eval x) * (eval y)

Давайте возьмем pretty-printer в качестве рабочего расширения:

module FormatExpr where
import Expr

class (Expr t) => FormatExpr t where
  format :: t -> String

instance FormatExpr Lit where
  format (Lit l) = show l

instance (FormatExpr a, FormatExpr b) => FormatExpr (Plus a b) where
  format (Plus x y) = "(" ++ (format x) ++ "+" ++ (format y) ++ ")"

И, наконец, в четвертом модуле два независимых расширения могут быть объединены:

module FormatExprWithMult where
import FormatExpr
import ExprWithMul

instance (FormatExpr a, FormatExpr b) => FormatExpr (Mul a b) where
  format (Mul x y) = "(" ++ (format x) ++ "*" ++ (format y) ++ ")"

Теперь о моей проблеме: обычно классы типов из haskell переводятся в концептуальный шаблон с имплицитами в Scala. Вот как далеко я зашел:

abstract class Expr[A] { // this corresponds to a type class
  def eval(e:A): Int;
}

case class Lit(v: Int)
implicit object ExprLit extends Expr[Lit] {
 def eval(e: Lit) = x.v;
}
case class Plus[A,B] (e1: A, e2: B) (implicit c1: Expr[A], c2: Expr[B])

Здесь я застрял на реализации неявного объекта для Plus. Как мне объявить неявный объект с параметрами типа и ограничениями?

Я знаю, что есть другие решения проблемы выражений в Scala, однако меня особенно интересует эта версия.

Спасибо всем за то, что прочитали мой отрывок длинный вопрос.

12
задан Don Stewart 22 April 2011 в 21:14
поделиться