Представьте язык, который не допускает создание нескольких конструкторов значений для типа данных. Вместо написания
data Color = White | Black | Blue
мы имели бы
data White = White
data Black = Black
data Blue = Black
type Color = White :|: Black :|: Blue
где :|:
(здесь он не |
, чтобы избежать путаницы с типами сумм) является встроенным оператором объединения типов. Соответствие шаблонов будет работать одинаково.
show :: Color -> String
show White = "white"
show Black = "black"
show Blue = "blue"
Как вы можете видеть, в отличие от копродуктов это приводит к плоской структуре, поэтому вам не нужно иметь дело с инъекциями. И, в отличие от типов сумм, он позволяет случайным образом комбинировать типы, что приводит к большей гибкости и детализации:
type ColorsStartingWithB = Black :|: Blue
Я считаю, что не будет проблемой также создавать рекурсивные типы данных
data Nil = Nil
data Cons a = Cons a (List a)
type List a = Cons a :|: Nil
Я знаю, что типы union присутствуют в TypeScript и, возможно, на других языках, но почему комитет Haskell выбрал ADT над ними?