Scala高级类型用法

的背景

我正在Scala的一个事件库中工作。 在我的图书馆中,您可以定义像这样的事件:

val e1 = new ImperativeEvent[Int]

你可以像这样触发它们:

e1(42)

你可以创建这样的反应:

val r1 = (i: Int) => println(i)

并将它们附加到这样的事件:

e1 += r1

还有一些其他的东西(比如事件转换,组合等)。 我使用Esper CEP引擎作为我的库的后端。 对于大多数操作,Esper使用称为EPL的类似SQL的语言。

问题

我试图实现一些更高级的概念,如事件连接。 所以现在你可以用多个属性来定义事件(使用元组类型):

val e2 = new ImperativeEvent[(Int, String)]

然后像这样加入他们:

val e3 = e1 join e2 windowLength (30) on "E1.P1 = E2.P1"

在它们各自的第一个属性相等的条件下,它们在e1和e2的最后30个发生处进行联合。

这是好的,但我想摆脱我的实现中的字符串,使事件表达式类型可检查。 我想将连接表达式更改为如下所示:

val e3 = e1 join e2 windowLength (30) on e1._1 === e2._1

类似于它在例如。 Squeryl。 这个问题是,我无法访问元组类型的元素的类型...

问题

我如何静态访问元组类型? 现在我只能通过反射来访问它们,这对我没有帮助。 我非常确定,我想实现的元组不可能与元组一起使用,但是我想知道使用无形库中的HLists或类似的东西可能有助于实现我的目标。


没有关于你的DSL的更多细节,恐怕不清楚“静态访问元组类型”的含义。 这是一个简化版的API,它不会遇到元组类型的问题:

class Event[T] {
  def joinOn[T2, R](ev2: Event[T2])(f: (T, T2) => R) = new Event[R]
}

你可以使用这个如下:

val e1 = new Event[(Int, String)]
val e2 = new Event[(Int, String)]
val e3 = e1.joinOn(e2)(_._1 == _._2)

应该很容易看出这可以扩展到支持你的join / windowLength / on语法。

更新:我可以看到你的用例很复杂,因为你需要将Scala编码的查询表达式翻译成另一种查询语言。 在这种情况下,您希望on方法的签名看起来像:

def on[T2, R](f: (Expr[T], Expr[T2]) => Expr[R]): Event[R]

在内部,每个事件对象都会创建自己的Expr表示,并将这个表示传递给提供给on方法的函数。

Expr类型可以被定义为:

trait Expr[T] {
  protected val repr: String

  def _1[A](implicit ev: T <:< Tuple2[A,_]): Expr[A] = 
    ??? // create an Expr[A] whose string representation is (repr + ".P1")

  // abstracting over tuple arities (using Shapeless)
  import shapeless._, nat._
  @scala.annotation.implicitNotFound("A tuple with at least 3 elements is required")
  type At2 = ops.tuple.At[T, _2]

  def _3(implicit at: At2): Expr[at.Out] = 
    ??? // create an Expr[at.Out] whose string representation is (repr + ".P3")

  def ===(other: Expr[T]): Expr[Boolean] =
    ??? // create an Expr[T] whose string representation is (repr + " = " + other.repr)
}

这显然很简单,但应该有助于开始。


I.有一个SynapseGrid功能反应式编程库。 在来源中你可以找到一些有用的提示。

库中的所有处理都是类型安全的。 你可以完全访问元组。

例如,如果我不得不在SynapseGrid中实现连接,我会定义一个以下签名的方法join

implicit class RichContact[T] (c:Contact[T]){ // contact == event in SynapseGrid's terminology
  ...
  def join[T2](c2:Contact[T2]):Contact[(T, T2)] = {
    // construct a contact/event that do nothing more than joining two events.
  }
}

implicit class RichTupledContact[T, T2](c:Contact[(T, T2)])
  def windowLength(len:Int):Contact[(T, T2)] = { 
    // construct the next step of processing events — window 
  }
}

等等。 逐渐建立事件处理大大简化了系统的构建。

II。 但是,如果您需要一次构建所有内容,则可以返回一些具有构建方法的中间对象:

implicit class RichContact[T] (c:Contact[T]){ // contact == event in SynapseGrid's terminology
  ...
  def join[T2](c2:Contact[T2]):Contact[(T, T2)] = {
    new {
      def windowLength(len:Int) = ...
    }
  }
}
链接地址: http://www.djcxy.com/p/74109.html

上一篇: Scala Advanced Type Usage

下一篇: Capitalize title page if