2014-03-19 4 views
2

Для пользовательского DSL у меня есть набор производителей и потребителей данных. (На самом деле это немного сложнее, но этого достаточно для установки проблемы.) Пользователи настраивают пользователя, для которого может потребоваться определенный тип данных. Я хотел бы убедиться, что система типов обеспечивает, чтобы правильный тип данных отправлялся правильному потребителю.Обратное наследование

Возможные разработки данных ограничены, поскольку можно написать один производитель данных, который может по крайней мере заполнить разумные значения по умолчанию. Таким образом, должна быть нижняя граница для всех типов данных, которая состоит из поставщика данных по умолчанию. Кроме того, все данные разделяют определенные характеристики, поэтому должна быть верхняя граница. И данные можно манипулировать таким образом, чтобы сохранить пригодность для данного потребителя, или которые расширяют пригодность для большего количества потребителей. Таким образом, типы должны выглядеть как

AllData <: D <: AnyData 

Что является (или большинство) компактного и элегантным способ кодирования этого ограничения в Scala, предполагая, что я на самом деле не хочу требовать AllData расширить любой другой тип данных D?

Прямо сейчас я просто суперкласс, который выглядит что-то вроде

class AnyData { 
    def foo: Int => String = defaultIntToStringImpl 
    def mapFoo(oo: String => String) = AllData((foo _) andThen oo) 
} 

и подклассы могут переопределить его

class LiteralNumberData extends AnyData { 
    override val foo = (i: Int) => i.toString 
} 

и есть случай, класс, который позволяет каждый метод быть подключаемыми

case class AllData(override val foo: Int => String) {} 

Но тогда потребители действительно могут выбирать только между AnyData и AllData, если они собираются разрешить сопоставления, потому что все отображения заканчиваются как AllData. Это не обеспечивает столько безопасности для потребителей, сколько я хотел бы, и это зависит от меня, чтобы я не забыл ничего не делать, например, LiteralNumberData, которые не могут быть упакованы в AllData.

ответ

2

Я хотел бы сделать ограничение по типам следующим образом:

trait ProdConsConstraint[Producer,Consumer]{ 
    type Output <: AnyData 
} 

, если я правильно следовать за вами. Затем вы можете использовать зависимые типы, чтобы обеспечить соответствие типов, с которыми вы работаете.

def foo(prod: Producer, con: Consumer)(implicit ev:ProdConsConstraint[Producer,Consuer]): ev.Output = ??? 

Это устраняет необходимость в нижней границе, а также позволяет вам свободу действий «открыть» вещи с помощью обзорного неявных параметров.

Хм ... это звучит слишком сложно. Возможно, я недостаточно понимаю этот вопрос.

+0

Нет, не слишком сложный; если что-либо, это не отражает полную проблему. Но частичные решения ценны! Я могу сделать некоторые проверки вручную, если это не так много. –

Смежные вопросы