使用implicits限制抽象类型成员约束的特征方法?

时间:2014-12-16 14:06:35

标签: scala type-conversion scalaz implicits

我遇到以下情况:

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具有不同的语义。

似乎leibniz替换不能/不能在这里工作(也许是因为它只用于带有单个参数的仿函数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, _]

如果这甚至有意义吗? 谢谢,

1 个答案:

答案 0 :(得分: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)
}