Tipos de soma - Por que no Haskell é `show (Int | Double)` diferente de `(show Int) | (mostre o dobro) `

9

Por que estes não são equivalentes?

show $ if someCondition then someInt else some double

e

if someCondition then show someInt else show someDouble

Entendo que se você isolar a if ... elseparte no primeiro exemplo de uma expressão por si só, não poderá representar seu tipo com um tipo de soma anônima Int | Double, como algo que você poderia fazer facilmente no TypeScript (mencionando o TypeScript porque é o langauge que eu costumava usar e que suporta tipos Sum), e teria que recorrer ao uso dos Eitherdados que seriam chamados show.

O exemplo que dei aqui é trivial, mas para mim faz mais sentido pensar "Ok, vamos mostrar algo, e que algo depende someCondition", em vez de "Ok, se algumaCondição for verdadeira, mostrar someInt caso contrário mostrar someDouble" e também permitir para menos duplicação de código (aqui o programa é repetido duas vezes, mas também pode ser uma aplicação de função longa e, em vez de uma if ... else, pode haver> 2 ramificações a serem consideradas)

Na minha opinião, deve ser fácil para o compilador verificar se cada um dos tipos que compõem o tipo de soma (aqui Int | Double) pode ser usado como parâmetro para showfuncionar e decide se os tipos estão corretos ou não. Melhor ainda é que a showfunção sempre retorna a stringqualquer que seja o tipo de parâmetro, portanto o compilador não precisa carregar todos os "desvios" possíveis (portanto, todos os tipos possíveis).

É por opção que esse recurso não existe? Ou está implementando mais difícil do que eu acho?

Mehdi Saffar
fonte
2
Um if ... then ... else ..., precisa ter o mesmo tipo na parte thene else. Você pode vê-lo como um operador ternário em algumas linguagens de programação.
Willem Van Onsem 9/11/19
11
Eu concordo com o making all conversions explicit. Na minha pergunta, não quero que Haskell faça uma conversão Intpara a Doubleou vice-versa. Eu apenas usei esses dois tipos como exemplo. Você pode substituir todos Intpor ae Doublecom bna minha pergunta, onde ambos os tipos derivam Show. Entendo que não existe anonymous sum typesem Haskell, mas gostaria de saber por que esse é o caso e o que está nos impedindo de projetar a linguagem para tê-la.
Mehdi Saffar
4
Eu acho que esses tipos são chamados de tipos de união . Um tipo de soma é essencialmente uma variante marcada do tipo de união, em que cada valor deve conter uma tag esquerda / direita além do valor do tipo interno. Espero que essa inferência de tipo com tipos de união, com todos os recursos de Haskell em nível de tipo, seja muito difícil de alcançar. Se x :: Int | Boole precisamos compilar show x, não há uma maneira fácil de saber qual ponteiro usar para chamar showem um RTS baseado em apagamento de tipo. Provavelmente precisaríamos manter algumas informações de nível de tipo em tempo de execução.
21419 chi
11
Não ter tipos de soma anônimos é uma decisão de design dos designers da Haskell. Não sei ao certo que tipo de benefício eles trariam para a mesa, mas vejo onde eles complicariam as coisas. Então, meu palpite é que eles são deixados de fora porque a relação custo / benefício não existe. Mas, para ter certeza absoluta, você precisa perguntar aos designers de idiomas originais e / ou mantenedores atuais. Eu não acho que seria uma ótima pergunta para o SO, porque há muitas opiniões e gostos pessoais envolvidos no design de um idioma.
n. 'pronomes' m.
4
(String, Int)não é anônimo. É apenas um tipo de produto comum com sintaxe engraçada. (String | Int)seria muito diferente. Comece perguntando se (Int|Int)deve ser idêntico Inte por quê.
n. 'pronomes' m.

Respostas:

8

Todas as partes de uma expressão devem ser bem digitadas. O tipo de if someCondition then someInt else someDoubleteria que ser algo como exists a. Show a => a, mas Haskell não suporta esse tipo de quantificação existencial.

Atualização: Como o chi aponta em um comentário , isso também seria possível se Haskell tivesse suporte para tipos de união / interseção (que não são iguais aos tipos de soma / produto), mas infelizmente não.

Joseph Sible-Restabelecer Monica
fonte
Você poderia elaborar a diferença entre os tipos de união / interseção e tipos de soma / produto? Eu sempre pensei que eles eram iguais, exceto pelo anonimato?
Mehdi Saffar
11
@MehdiSaffar Anonymous como não marcado, não como em um construtor não identificado. Em outras palavras, se você tiver um Int ∪ Double, saberá que possui um dos dois, mas não poderá padronizar a correspondência para ver qual, portanto, você só pode fazer coisas que seriam válidas para ambas as possibilidades.
Joseph Sible-Reinstate Monica
2
Para maior clareza, o TypeScript possui informações de tipo disponíveis em tempo de execução, por isso possui um typeofoperador que pode compensar a falta de marcação e ver qual tipo é usado de qualquer maneira. Haskell é totalmente apagado, por isso, se suportasse esse recurso, não haveria equivalente a isso.
Joseph Sible-Reinstate Monica
7

Existem tipos de produtos com sintaxe leve, escritos (,), em Haskell. Uma coisa seria que um tipo de soma com uma sintaxe leve, algo como (Int | String), seria uma ótima idéia. A realidade é mais complicada. Vamos ver o porquê (estou tomando algumas liberdades Num, elas não são importantes).

if someCondition then 42 else "helloWorld"

Se isso deve retornar um valor do tipo like (Int | String), então o que deve retornar a seguir?

if someCondition then 42 else 0

(Int | Int)obviamente, mas se isso é distinto da planície, Intentão estamos com problemas profundos. Portanto, (Int | Int)deve ser idêntico ao simples Int.

Pode-se ver imediatamente que essa não é apenas uma sintaxe leve para tipos de soma, mas um recurso de linguagem totalmente novo. Um tipo diferente de sistema de tipos, se você preferir. Deveríamos ter um?

Vamos olhar para esta função.

mysteryType x a b = if x then a else b

Agora que tipo mysteryTypetem? Obviamente

mysteryType :: Bool -> a -> b -> (a|b)

direita? Agora, o que se ae bsão do mesmo tipo?

let x = mysteryType True 42 0

Isso deve ficar claro Intcomo concordamos anteriormente. Agora, mysteryTypeàs vezes, retorna um tipo de soma anônima e, às vezes, não, dependendo dos argumentos que você passa. Como você padronizaria essa expressão? O que diabos você pode fazer com isso? Exceto coisas triviais como "show" (ou quaisquer métodos de outras classes de tipos dos quais seria uma instância), não muito. A menos que você adicione informações do tipo em tempo de execução ao idioma, isto é, ele também typeofestá disponível - e isso faz do Haskell um idioma totalmente diferente.

Então sim. Por que Haskell não é um TypeScript? Porque não precisamos de outro TypeScript. Se você deseja TypeScript, sabe onde encontrá-lo.

n. 'pronomes' m.
fonte
11
@MichaWiedenmann Francamente, não sei se "relevante" é a palavra certa. Eu acho que é útil de uma maneira ou de outra. Sim, parei por um momento e pensei em incluí-lo. Mas sou conhecido por estar errado às vezes.
n. 'pronomes' m.
Não tem problema, é o seu post, você decide.
Micha Wiedenmann
Então, quais são seus pronomes?
Dfeuer