我正在尝试构建一个非常通用的解算器系统。我的目标是让不同的问题空间(图形着色,背包打包等)与各种抽象求解器(分支定界,局部搜索)以及各种具体策略(如具体的"善良& #34;功能)。我可以将其与泛型一起使用,但很难将所有配置集中到一个地方。我的理论是,蛋糕和抽象类型在这里会更好。
考虑一个想要做蛋糕的贝克。
val ingredients: Set[Ingredient] = shopper.shop
val cake: Cake = baker.bake(ingredients)
shipper.ship(cake)
Ingredient
和Cake
是未知类型,可能绝对是任何类型。我们所知道的是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)
这不错,可以升级到一个单独的对象来捕获完整的配置。也许这是正确的方法。