在Scala中使用代数数据类型时的方法定义

时间:2016-12-09 01:02:38

标签: scala abstract-data-type

我想在Scala中实现一个库。 我刚刚开始,我已经无法以模块化和可扩展的方式设计它。

我需要一些帮助!例如,我已经定义了一个树ADT

sealed trait Tree[+A,+B,+C]
case object EmptyTree extends Tree[Nothing, Nothing, Nothing]
case class Leaf[A,B,C](value: C) extends Tree[A,B,C]
case class Branch_A1[A,B,C](op: B, left: Tree[A,B,C]) extends Tree[A,B,C]
case class Branch_A2[A,B,C](op: A, left: Tree[A,B,C], right: Tree[A,B,C]) extends Tree[A,B,C]

Branch_A#表示具有参数的函数。你可以看到它的发展方向。

为什么A,B和C?因为Leafs将是例如Double,我有两种类型的函数Double =>双和(双,双)=>双。当我增加分支的数量多样性时,我担心这会如何扩展。我想让这个非常灵活

我有两个问题,一个是技术问题,另一个是关于我的设计模式。

技术问题

当我尝试定义泛型方法来操作这样的结构时,我得到编译错误,这是我无法解决的。例如:

sealed trait Tree[+A,+B,+C] {
  def evaluateTree[A,B,C] (t: Tree[A,B,C]): C = t match {
    case Leaf(value) => value
    case Branch_A1(op, left) => op(evaluateTree(left))
    case Branch_A2(op, left, right) => op(evaluateTree(left),evaluateTree(right))
  }
}
case object EmptyTree extends Tree[Nothing, Nothing, Nothing]
case class Leaf[A,B,C](value: C) extends Tree[A,B,C]
case class Branch_A1[A,B,C](op: B, left: Tree[A,B,C]) extends Tree[A,B,C]
case class Branch_A2[A,B,C](op: A, left: Tree[A,B,C], right: Tree[A,B,C]) extends Tree[A,B,C]

op(evaluateTree(left))我得到“应用程序不支持参数”。我不明白为什么。

设计问题

如果允许图书馆的用户表达更高的arity功能的域,则这将难以管理。我想,泛型类型的数量会爆炸。我怎样才能以更好的方式设计它?我想让这个可扩展。通用类型的使用是最合适的吗?还是应该换个方式?我读到有关抽象数据类型的替代方法

2 个答案:

答案 0 :(得分:0)

技术问题:编译器没有足够的有关AB的信息,无法知道op(...)是否可能/允许,或者如果被调用,它将返回正确的类型。

如果(使用更简单的例子)你写了case Leaf(value) => value-1怎么办?除非已将C定义/限制为某些已知具有匹配返回类型的-(x:Int)方法的类型子集,否则编译器不会允许这样做。

答案 1 :(得分:0)

在第二天,我再次看到问题,这一切都有意义。只是我让仿制药比实际上复杂得多。

我之前曾说过,仿制药类型[A,B,C]可能意味着[(Double,Double)=> Double,Double =>双,双]。所以我只需要一个参数化类型:

sealed trait Tree[+A]
case object EmptyTree extends Tree[Nothing]
case class Leaf[A](value: A) extends Tree[A]
case class Branch_A1[A](op: A => A, left: Tree[A]) extends Tree[A]
case class Branch_A2[A](op: (A,A) => A, left: Tree[A], right: Tree[A]) extends Tree[A]