Tipi di somma - Perché in Haskell è `show (Int | Double)` diverso da `(show Int) | (mostra Double) `


9

Perché questi non sono equivalenti?

show $ if someCondition then someInt else some double

e

if someCondition then show someInt else show someDouble

Capisco che se si isola la if ... elseparte nel primo esempio in un'espressione da sola, non è possibile rappresentare il suo tipo con un tipo di somma anonimo, il tipo di Int | Double, come qualcosa che si potrebbe fare facilmente in TypeScript (menzionando TypeScript perché è il langauge che ho usato spesso e che supporta i tipi di somma), e dovrei ricorrere all'utilizzo dei Eitherdati che poi basandomi su di esso chiamerebbe show.

L'esempio che ho dato qui è banale, ma per me ha più senso pensare "Va bene, mostreremo qualcosa, e quel qualcosa dipende da someCondition" piuttosto che "Va bene, se alcune condizioni sono vere, quindi mostra alcune, altrimenti mostra alcune cose doppie", e permette anche per una duplicazione del codice minore (qui lo spettacolo viene ripetuto due volte ma potrebbe anche essere un'applicazione con funzione lunga e al posto di un if ... elseci potrebbero essere> 2 rami da considerare)

Nella mia mente dovrebbe essere facile per il compilatore verificare se ciascuno dei tipi che rendono il tipo di somma (qui Int | Double) possa essere usato come parametro per showfunzionare e decide se i tipi sono corretti o meno. Ancora meglio è che la showfunzione restituisce sempre stringnon importa i tipi di parametri, quindi il compilatore non deve portare con sé tutti i possibili "rami" (quindi tutti i tipi possibili).

È per scelta che una tale funzione non esiste? O è più difficile implementarlo?


2
An if ... then ... else ..., deve avere lo stesso tipo nella parte thene else. Puoi vederlo come un operatore ternario in alcuni linguaggi di programmazione.
Willem Van Onsem,

1
Sono d'accordo sul making all conversions explicit. Nella mia domanda, non voglio che Haskell lanci an Inta Doubleo viceversa. Ho appena usato questi due tipi come esempio. Potresti sostituire ogni Intcon ae Doublecon bnella mia domanda da cui derivano entrambi i tipi Show. Capisco che non ci sono anonymous sum typesin Haskell ma vorrei sapere perché è così e cosa ci impedisce di progettare il linguaggio per averlo.
Mehdi Saffar,

4
Penso che tali tipi siano chiamati tipi di unione . Un tipo di somma è essenzialmente una variante con tag del tipo di unione, in cui ogni valore deve contenere un'etichetta sinistra / destra oltre il valore del tipo interno. Mi aspetto che l'inferenza del tipo con i tipi di unione, con tutte le funzionalità a livello di tipo di Haskell sia molto difficile da ottenere. Se x :: Int | Boole dobbiamo compilare show x, non esiste un modo semplice per sapere quale puntatore a funzione utilizzare per chiamare show, in un RTS basato sulla cancellazione del tipo. Probabilmente avremmo bisogno di mantenere alcune informazioni a livello di tipo in fase di esecuzione.
Chi

1
Non avere tipi di somma anonimi è una decisione di progettazione dei designer Haskell. Non sono sicuro del tipo di beneficio che porterebbero sul tavolo, ma vedo dove potrebbero complicare le cose. Quindi la mia ipotesi è che sono esclusi perché il rapporto costi / benefici non è lì. Ma per essere assolutamente sicuri, devi chiedere ai progettisti della lingua originale e / o ai manutentori attuali. Non penso che sarebbe una grande domanda SO, perché ci sono molte opinioni e gusti personali coinvolti nella progettazione di una lingua.
n. 'pronomi' m.

4
(String, Int)non è anonimo. È solo un tipo di prodotto normale con sintassi divertente. (String | Int)sarebbe molto diverso. Inizia chiedendoti se (Int|Int)dovrebbe essere identico Inte perché.
n. 'pronomi' m.

Risposte:


8

Tutte le parti di un'espressione devono essere ben digitate. Il tipo di if someCondition then someInt else someDoubledovrebbe essere qualcosa di simile exists a. Show a => a, ma Haskell non supporta questo tipo di quantificazione esistenziale.

Aggiornamento: come sottolinea Chi in un commento , ciò sarebbe possibile anche se Haskell avesse il supporto per tipi di unione / intersezione (che non sono uguali ai tipi di somma / prodotto), ma sfortunatamente non lo è.


Potresti per favore approfondire la differenza tra tipi di unione / intersezione e tipi di somma / prodotto? Ho sempre pensato che fossero gli stessi, tranne l'anonimato?
Mehdi Saffar,

1
@MehdiSaffar Anonimo come in un senza tag, non come in un costruttore senza nome. In altre parole, se ne hai uno Int ∪ Double, allora sapresti che hai uno dei due, ma non saresti in grado di modellare la corrispondenza per vedere quale, quindi potresti fare solo cose che sarebbero valide per entrambe le possibilità.
Joseph Sible: ripristina Monica il

2
Per chiarezza, TypeScript ha informazioni sul tipo disponibili in fase di esecuzione, quindi ha un typeofoperatore che può compensare la mancanza di tag e vedere quale tipo viene comunque utilizzato. Haskell viene completamente cancellato, quindi se supportasse questa funzione, non ci sarebbe alcun equivalente.
Joseph Sible: ripristina Monica il

7

Esistono tipi di prodotti con sintassi leggera, scritti (,) in Haskell. Uno direbbe che un tipo di somma con una sintassi leggera, qualcosa del genere (Int | String), sarebbe un'ottima idea. La realtà è più complicata. Vediamo perché (mi sto prendendo delle libertà Num, non sono importanti).

if someCondition then 42 else "helloWorld"

Se questo dovesse restituire un valore di tipo like (Int | String) , quale dovrebbe essere il seguente ritorno?

if someCondition then 42 else 0

(Int | Int)ovviamente, ma se questo è distinto dalla pianura, Intallora siamo in grossi guai. Quindi (Int | Int)dovrebbe essere identico al semplice Int.

Si può immediatamente vedere che questa non è solo una sintassi leggera per i tipi di somma, ma una funzionalità del linguaggio completamente nuova. Un diverso tipo di sistema di tipi, se vuoi. Dovremmo averne uno?

Diamo un'occhiata a questa funzione.

mysteryType x a b = if x then a else b

Ora che tipo fa mysteryType ha? Ovviamente

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

destra? Ora cosa succede se aeb sono dello stesso tipo?

let x = mysteryType True 42 0

Questo dovrebbe essere chiaro Intcome abbiamo concordato in precedenza. Ora a mysteryTypevolte restituisce un tipo di somma anonima, a volte no, a seconda degli argomenti passati. In che modo corrisponderesti a una simile espressione? Cosa diavolo puoi farci? Tranne cose banali come "show" (o qualunque metodo di altre classi di tipo sarebbe un'istanza di), non molto. A meno che non si aggiungano informazioni sul tipo di runtime alla lingua, ovvero typeofsono disponibili, e ciò rende Haskell una lingua completamente diversa.

Quindi si Perché Haskell non è un TypeScript? Perché non abbiamo bisogno di un altro TypeScript. Se vuoi TypeScript, sai dove trovarlo.


1
@MichaWiedenmann Francamente non so se "pertinente" sia la parola giusta. Penso che sia utile in un modo o nell'altro. Sì, mi sono fermato per un momento e ho pensato di includerlo. Ma sono noto per essere sbagliato a volte.
n. 'pronomi' m.

Nessun problema, è il tuo post, decidi tu.
Micha Wiedenmann,

Quindi quali sono i tuoi pronomi?
decimo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.