Генеральное создание трейтов в scala

Я пытаюсь создать систему, которая позволяет пользователям объединять в цепочку несколько процессоров. Моя трудность заключается в том, что у каждого процессора на самом деле есть два бита информации, о которых он заботится, и я хочу, чтобы они обрабатывались безопасным для типов способом. Я свел это к этой проблеме:

Данный:

//First family of stuff
trait A {
  def doA {}
}

trait B {
  def doB {}
} 

//Second family of stuff
trait X {
  def doX {}
}

trait Y {
  def doY {}
} 

Я могу объединить элементы из двух семейств вместе в 4 вкуса:

var f = new A with X {}
f.doA
d.doX

var g = new A with Y {}
//...

Здорово. Проблема в том, что я хочу, чтобы каждая из функций (doA и т. Д.) Возвращала комбинацию двух типов, чтобы я мог связать вещи вместе. По сути, я хочу сделать: trait A {def doThing = {new A with ThingThatImMixedInWithLikeXOrY {}}}

Каждый процессор должен возвращать анонимный класс, который состоит из 1) типа, известного процессору 2) типа, с которым он был смешан.

Моим первым ударом было использование дженериков, примерно так:

trait A {
  this : {def makeWithT[TOther]} =>
  def doA = makeWithT[B]
}

trait B {
  this : {def makeWithT[TOther]} =>
  def doB = makeWithT[A]
}

trait X {
  this : {def makeWithS[TOther]} =>
  def doX = makeWithT[Y]
}

trait Y {
  this : {def makeWithS[TOther]} =>
  def doY = makeWithT[Y]
}

class Foo[T, S] extends S with T {
  def makeWithT[OtherT] = new T with OtherT
  def makeWithS[OtherT] = new S with OtherT
}

var f = new Foo[A, X]
f.doA.doB
f.doX.doA
f.doX.doY
...

Очевидно, я столкнулся с целым рядом проблем:

  1. Я не могу создать общий класс, который расширяется от параметров типа

  2. Я не могу создать экземпляр своего анонимного класса с помощью универсального параметра

  3. Я не могу определить возвращаемый тип функций в трейте, потому что я не знаю тип, пока он не смешается с чем-то.

Я немного новичок, когда дело доходит до scala, и у меня такое чувство, что я делаю это совершенно неправильно и, возможно, мне следует использовать имплициты и шаблон CanBuildFrom. Любая помощь будет принята с благодарностью.

Ваше здоровье


person Tom Peck    schedule 01.06.2012    source источник
comment
Вы минимизировали проблему и сделали ее очень абстрактной. В некоторых случаях это может быть хорошо, но я думаю, что в данном конкретном случае будет более полезным, если вы опишете нам конкретную проблему и цель, которую хотите заархивировать. Насколько я понимаю, в этом вопросе вы описываете (неработающее) решение проблемы, о которой мы еще не знаем. Если вы поделитесь им с нами, возможно, мы сможем предложить другое / лучшее / рабочее решение проблемы, с которой вы сейчас сталкиваетесь ...   -  person tenshi    schedule 01.06.2012
comment
Хорошо, начнем. Я хочу иметь грамматику, чтобы я мог делать такие вещи, как dataSource.map (...). Filter (...), где dataSource - это мой собственный тип потока. Проблема в том, что есть другие операции, которые я хочу выполнить с ним, которые не являются преобразованиями, а скорее модификациями того, как выполняются вычисления. Например, я мог бы захотеть сделать datasource.asParallel.filter (...). AsSequential. Это немного надуманный пример, но вы можете видеть, что у меня есть две группы операций. Тип возврата asParallel должен быть чем-то, что предоставляет операцию asSequential.   -  person Tom Peck    schedule 01.06.2012


Ответы (1)


Наиболее известным решением для стекируемых процессоров является стекируемая функция.

http://www.artima.com/scalazine/articles/stackable_trait_pattern.html

trait StackableRoot {
  def StackablePass (x:Int) : x
}
trait StackableDouble extends StackableRoot {
  def internalPass (x:Int) = 2*x
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}
trait StackableIncrement extends StackableRoot {
  def internalPass (x:Int) = x+1
  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}

есть какой-то шаблон с

  abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))

Этого нельзя избежать, упаковав в параметризованный типаж, поскольку для этого потребуется scala для наследования некоторого трейта с разными параметрами несколько раз, что запрещено известным стиранием типа.

person ayvango    schedule 01.06.2012