2012-04-20 13 views
13

Sono un nuovo arrivato ad Haskell e sto attualmente passando per Real World Haskell. Il libro dice che il costruttore del tipo è usato solo nella firma del tipo mentre il costruttore del valore è usato nel codice reale. Fornisce anche un esempio di una dichiarazione per mostrare che i nomi di entrambi sono indipendenti l'uno dall'altro. Perché sono necessari due costruttori in primo luogo, se solo uno di essi è utilizzato nel codice reale? Dal momento che non useremmo il costruttore di tipi nel codice reale, a che scopo serve il costruttore del tipo?Perché esiste un costruttore di valori oltre al costruttore di tipi in Haskell?

+11

La frase "codice effettivo" è sfortunata, perché implica che non si userebbe il costruttore di tipi nei programmi, quando gli autori in realtà intendevano che i costruttori di tipo sono usati solo per le annotazioni di tipo. Questo equivale a dire che non hai bisogno delle parole chiave "int" o "long" in C perché non le usi nel codice reale (vengono utilizzate solo nelle dichiarazioni, che non contano come "codice effettivo" "con questo standard). –

+0

... no accetta? :) –

risposta

22

Forse i nomi sono un po 'fuorvianti. Un costruttore di tipo rappresenta il nome del tipo che stai dichiarando. Si chiamano così perché costruiscono tipi, non valori: infatti, essendo (possibilmente) parametrizzati su variabili di tipo definiscono una famiglia di tipi. Agiscono come i modelli di C++ e i generici di Java. In data MyType a b = Constr a b, MyType è un tipo di costruttore che accetta due tipi a e b per creare un nuovo tipo (MyType a b).

A Il costruttore di valore è l'unica parte che si chiama "costruttore" in altre lingue (orientate agli oggetti), poiché è necessaria per creare valori per quel tipo. Pertanto, nell'esempio precedente, se si assume il valore Constr :: a -> b -> MyType a b, è possibile creare un valore Constr "abc" 'd' :: MyType [Char] Char.

+2

Posso chiedere come migliorare la mia risposta per sbarazzarmi di quel -1? Cosa c'è che non va? –

7

Un modo conveniente per ottenere l'intuizione tipi e valori è che i primi sono fase di compilazione valori, mentre i secondi sono runtime valori. In altre parole, i costruttori di tipo sono costruttori di valori nel set di Haskell Types, al solo scopo di digitare il programma in fase di compilazione. Ciò significa anche che non è possibile costruire un tipo in fase di esecuzione e non è possibile creare un valore in fase di compilazione.

Quindi, poiché non è possibile diramare esplicitamente in fase di esecuzione sulla base di un valore di tipo (sebbene sia possibile implicitamente con le classi di caratteri), i costruttori di tipo sono totalmente inutili come oggetti di runtime e in molti casi sono totalmente assenti l'ultimo binario. Viceversa, poiché i costruttori di valori consentono di costruire valori nell'insieme del loro tipo in fase di esecuzione, sono totalmente inutili come oggetto in fase di compilazione.

A causa di questa semplice proprietà, i costruttori di tipo ei costruttori di valori possono condividere nomi in modo univoco.

+0

Questa è la risposta più semplice da capire per le persone che provengono da uno sfondo imperativo! –

16

È un po 'come dire "perché abbiamo bisogno di classi e oggetti se gli oggetti sono l'unica cosa che viene effettivamente eseguita?"

I due tipi di costruttori svolgono diversi lavori. I costruttori di tipo vanno in firme di tipo. I costruttori di valore vanno in codice eseguibile.

Nel caso più semplice, un tipo "costruttore" è solo un nome di tipo. Nel caso più semplice, un tipo ha solo un costruttore di valori. Così si finisce con le cose come

data Point = Point Int Int

Si potrebbe dire a te stesso "ora perché diamine a Ho bisogno di scrivere Point due volte?"

Ma ora consideriamo un esempio meno banale:

data Tree x = Leaf x | Branch (Tree x) (Tree x)

Qui Tree è un costruttore di tipo.Gli dai un argomento di tipo e "costruisce" un tipo. Quindi Tree Int è un tipo, Tree String è un altro tipo e così via. (Come modelli in C++, o generici in Java o Eiffel.)

D'altra parte, Leaf è un costruttore di valori. Dato un valore, ne fa un albero a 1 nodo. Quindi Leaf 5 è un valore Tree Int, Leaf "banana" è un valore Tree String e così via.

Analogamente per Branch. Prende due valori dell'albero e costruisce un nodo dell'albero con quegli alberi come bambini. Ad esempio, Branch (Leaf 2) (Leaf 7) è un valore Tree Int.

+0

Grazie per la spiegazione dettagliata! –

Problemi correlati