Традиционный подход к алгебраическим типам рекомендует что-то вроде этого:
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
Но иерархии объектов могут возникать только в одном направлении.
Поэтому необходимо каким-то другим способом определить алгебраические типы. Для этого есть место, так как бесконечное расширение исходного трейта не является чем-то действительно необходимым, и большинство таких трейтов используется с ключевым словом запечатан. Поэтому для представления типов данных может использоваться какой-то другой, менее мощный механизм, чем расширение.
CompositeType
дальше (в других местах), потому что этоsealed
? - person Malte Schwerhoff   schedule 05.03.2013