Por que precisamos de tipos de soma?

Imagine uma linguagem que não permita vários construtores de valor para um tipo de dados. Em vez de escrever

data Color = White | Black | Blue

Nós teríamos

data White = White
data Black = Black
data Blue = Black
type Color = White :|: Black :|: Blue

Onde:|: (aqui não é| para evitar confusão com tipos de soma) é um operador de união de tipo interno. A correspondência de padrões funcionaria da mesma maneira

show :: Color -> String
show White = "white"
show Black = "black"
show Blue = "blue"

Como você pode ver, ao contrário dos coprodutos, resulta em uma estrutura plana, para que você não precise lidar com injeções. E, diferentemente dos tipos de soma, permite combinar tipos aleatoriamente, resultando em maior flexibilidade e granularidade:

type ColorsStartingWithB = Black :|: Blue

Eu acredito que não seria um problema construir tipos de dados recursivos também

data Nil = Nil
data Cons a = Cons a (List a)
type List a = Cons a :|: Nil

Sei que tipos de união estão presentes no TypeScript e provavelmente em outras linguagens, mas por que o comitê Haskell escolheu os ADTs sobre eles?

questionAnswers(4)

yourAnswerToTheQuestion