用共享类型烘焙Scala蛋糕

时间:2014-03-17 19:13:46

标签: scala

我正在尝试构建一个非常通用的解算器系统。我的目标是让不同的问题空间(图形着色,背包打包等)与各种抽象求解器(分支定界,局部搜索)以及各种具体策略(如具体的"善良& #34;功能)。我可以将其与泛型一起使用,但很难将所有配置集中到一个地方。我的理论是,蛋糕和抽象类型在这里会更好。

考虑一个想要做蛋糕的贝克。

val ingredients: Set[Ingredient] = shopper.shop
val cake: Cake = baker.bake(ingredients)
shipper.ship(cake)

IngredientCake是未知类型,可能绝对是任何类型。我们所知道的是shop()返回成分,bake()将它们转换为蛋糕,而ship()将接受该蛋糕。我试图这样做(我不确定我是否正确使用自我类型):

override def main(args: Array[String]): Unit = {
  val shopper = new IntShopper
  val baker = new IntBaker

  val ingredients = shopper.shop
  val cake = baker.bake(ingredients)
  ...
}

trait Bakery {
  type Cake
  type Ingredient
  type Recipe <: bakery.Recipe
}

trait IntBakery extends Bakery {
  override type Recipe = SummingRecipe
  override type Ingredient = Int
  override type Cake = Long
}

trait Shopper {
  self: Bakery =>
  def shop: Set[Ingredient]
}

class IntShopper extends Shopper {
  self: IntBakery =>
  override def shop: Set[Ingredient] = Set(1,2,3)
}

trait Recipe {
  self: Bakery =>
  def combine(is: Set[Ingredient]): Cake
}

trait Baker {
  self: IntBakery =>
  def bake(ingredients: Set[Ingredient]): Cake = (new Recipe).combine(ingredients)
}

[...]

这是它崩溃的地方。 Ingredient有多个与路径相关的版本,我不知道我是如何设计它的,以便它们全部统一。

我的最终目标是能够混合几个这样的混凝土碎片:

 val shopper = new Shopper with IntShopping with Jeep
 val baker = new Baker with IntBaking with SummingRecipe with WoodfireStove with PlasticSpoon

(或更具体地说:)

 val solver = new Solver with GraphColoring with LocalSearch with ColorReduction with RandomChanges

Solver需要一个问题空间(GraphColoring),它需要一个需要策略(ColorReduction)的求解器(LocalSearch),它需要一种特殊的创建新状态的方法(RandomChanges)。感觉这就是抽象类型的用途,但我无法实现这一目标。


关于@ mrhobo的问题,可能是正确的方法,而且我现在就是这样做的。它只是感觉不灵活。我目前有:

trait Solver[InputData, Solution]

trait LocalSearchSolver[InputData, Solution] extends Solver[InputData, Solution] {
  val firstSolver: SingleSolver[InputData, Solution]
  ...
}

trait GCSolver extends Solver[InputData, Solution]

class GCMaxMinSolver extends GCSolver with LocalSearchSolver[InputData, Solution] {
  override val firstSolver = new GCGreedySolver
}

class GCGreedySolver extends GCSolver with SingleSolver[InputData, Solution]

trait SingleSolver[InputData, Solution] extends Solver[InputData, Solution]

首先,似乎有很多重复的&#34; InputData,Solution&#34;,我无法弄清楚如何混合firstSolver。 LocalSearch需要助手解算器,但其他求解器不需要。我试过这个:

trait LocalSearchSolver[InputData, Solution, FirstSolver <: SingleSolver[InputData, Solution] ] extends Solver[InputData, Solution] {

但它抱怨它无法解析new FirstSolver的FirstSolver。


啊,现在我觉得我到了某个地方:

class GCMaxMinSolver(val firstSolver: GCSolver with SingleSolver[InputData, Solution]) 
  extends GCSolver with LocalSearchSolver[InputData, Solution] {

现在mixin看起来像:

val solver = new GCMaxMinSolver(new GCGreedySolver)

这不错,可以升级到一个单独的对象来捕获完整的配置。也许这是正确的方法。

0 个答案:

没有答案