0

我处于以下情况:

import scalaz.Leibniz._

trait Exp[T, C] {

   def &&(that: Exp[T, C])(implicit evT: T === Boolean) = LogicalAnd(this, that)
   def &&(that: Exp[T, C])(implicit evT: T === Int) = BitwiseAnd(this, that)

}

case class LogicalAnd[C](e1: Exp[Boolean, C], e2: Exp[Boolean, C]) extends Exp[Boolean, C] 
case class LogicalOr[C](e1: Exp[Boolean, C], e2: Exp[Boolean, C]) extends Exp[Boolean, C] 
...
case class BitwiseAnd[C](e1: Exp[Int, C], e2: Exp[Int, C]) extends Exp[Int, C]
case class BitwiseOr[C](e1: Exp[Int, C], e2: Exp[Int, C]) extends Exp[Int, C]
...

特征 Exp[T,C] 是 DSL 的基本特征和 AST,我想在这个特征中重载内置的 scala 运算符以允许在这个 dsl 上使用中缀符号,但是我想限制其中的一些方法在特征级别对类型 T 进行了限制,因此此处的相同操作 '&&' 具有不同的语义,具体取决于类型 T。

似乎莱布尼茨替代在这里不起作用/不能起作用(可能是因为它只为具有单个参数的函子 F[_] 定义):

[error] /home/remi/Projects/DSL/src/main/scala/Exp.scala:80: type mismatch;
[error]  found   : exp.Exp[T,C]
[error]  required: exp.Exp[Boolean,?]
[error]   = LogicalAnd(this, that)
[error]         ^

这种限制特征 T 参数的方法是否有意义?有没有办法通过“隐藏”第二个参数 C 来使莱布尼茨在这种情况下工作:

type ExpF[T] = Exp[T, _]

如果这有道理吗?谢谢,

4

1 回答 1

0

正是这样;定义这样的类型,然后使用Leibniz.lift来提升你的Leibniz

def &&(that: Exp[T, C])(implicit evT: T === Boolean) = {
  type ExpF[A] = Exp[A, C]
  val ev2: (Exp[T, C] === Exp[Boolean, C]) =
    Leibniz.lift[⊥, ⊥, ⊤, ⊤, ExpF, T, Boolean](evT)
  LogicalAnd(this, that)
}
于 2014-12-16T16:01:39.890 回答