эмулировать расширяемые алгебраические типы на scala

Традиционный подход к алгебраическим типам рекомендует что-то вроде этого:

sealed trait CompositeType
final case class LeftBranch(left : String) extends CompositeType
final case class RightBranch(right : Int) extends CompoisteType
object Trivial extends CompositeType

Проблема в том, что я не могу расширить CompositeType дальше, чтобы иметь больше возможностей (точно так же, как Double расширяет Float, предлагая большую точность и предоставляя систему для обратного преобразования из Double в Float).

Scala позволяет вам свободно определять собственные методы применения и отмены для создания и сопоставления экземпляров алгебраического типа.

Есть ли какой-нибудь проект, который пытается создать структуру для таких типов?

Это может быть полезно для метафоры актеров. В настоящее время акторы получают нетипизированные сообщения (поскольку Any не подразумевает ограничений по типам), соответствующие известным типам и предоставляющие безопасное значение по умолчанию для других. Это нарушает строгий дизайн scala для всех типов, и было бы очень приятно ограничить актеров более правильными типами.


обновление:

Пример, разъясняющий мои намерения:

sealed trait CompositeType1
final case class OtherBranch(x : Int, y : Int) extends CompositeType1
object Simple extends CompositeType1

trait ComplexChoice extends CompositionType with CompositionType1

Я хочу создать CompositionType не как корень в иерархии типов, а как один сплошной класс. Это может быть расширено дальше, смешиваясь с другими классами.

Давайте посмотрим на обычное использование ООП:

trait ContractOne
trait ContractTwo

def method(arg : ContractOne with ContractTwo)

В этом примере функции method нужен аргумент, который подходит для обоих контрактов. Что означает контракт для алгебраического типа? Набор доступных конструкторов и сопоставителей. Каков естественный взгляд на расширение алгебраического типа? Расширение набора конструкторов некоторыми новыми значениями (так же, как Double расширяет Float более точными числами с плавающей запятой)

CompositeType явно пропускает эту концепцию. Если я смешаю эти два алгебраических типа, я получу множество пересечений вместо объединения. Это прямое следствие выбранного способа представления алгебраических типов в виде множества иерархических подтипов. Это дает больше свободы выбора за пределами исходных типов, но ему не хватает функций ООП, поскольку наследование используется для построения элементов и не может использоваться для расширения самих алгебраических типов.

В Haskell есть только один способ добавления новых вариантов выбора в алгебраический тип:

data CompositeType = LeftBranch String | RightBranch Int | Trivial
data CompositeType1 = OtherBranch Int Int | Simple
data ComplexChoice = CompositeType | CompositeType1

ComplexChoice легко определяется в концепции типов данных Haskell. Но работать с этим становится сложно, так как мне нужно перенаправить все методы для композиции. Вот почему композиция — это решение в scala, но хлопотное и шаблонное (если нет плагина компилятора, который может генерировать код для шаблона композиции)

Что мне действительно нужно, это что-то вроде этого:

ComplexChois condense CompositeType and CompositeType1

Но иерархии объектов могут возникать только в одном направлении.

Поэтому необходимо каким-то другим способом определить алгебраические типы. Для этого есть место, так как бесконечное расширение исходного трейта не является чем-то действительно необходимым, и большинство таких трейтов используется с ключевым словом запечатан. Поэтому для представления типов данных может использоваться какой-то другой, менее мощный механизм, чем расширение.


person ayvango    schedule 04.03.2013    source источник
comment
Ваша проблема в том, что вы не можете расширить CompositeType дальше (в других местах), потому что это sealed?   -  person Malte Schwerhoff    schedule 05.03.2013
comment
нет. Я хочу, например, создать отдельное дерево типов CompositeType1 и сделать смесь CompositeType с CompositeType1.   -  person ayvango    schedule 07.03.2013
comment
Взгляните на stackoverflow.com /questions/3508077/ относится к типам объединений.   -  person Malte Schwerhoff    schedule 07.03.2013
comment
О, пропустил при поиске. Строгая типизация по типам союзов - это то, что мне действительно нужно.   -  person ayvango    schedule 07.03.2013


Ответы (1)


Как вы заметили, objects - это конец строки для вывода подтипов. В этом случае вы могли бы создать еще один уровень промежуточного абстрактного типа, из которого можно получить подтипы (одноэлементные или иные) Trivial:

sealed trait Trivial extends CompositeType
object Trivia extends Trivial { ... }
class Triviality extends Trivia(...) { ... } \
...
person Randall Schulz    schedule 04.03.2013
comment
Конечно, вы можете продолжить ветку CompositeType. Но все это по-прежнему будет CompositeType. Я не могу смешать какой-либо другой трейт с CompositeType. Что-то вроде trait SuperComposite extends CompositeType with OtherComposite и SuperComposite получило наследников CompositeType и OtherComposite как своих собственных наследников. - person ayvango; 04.03.2013