Qual è il presupposto fatto in "Learn You a Haskell" quando si deduce il tipo?


18

Questa domanda non è soggettiva. Nel libro di riferimento viene usato un verbo molto specifico, e mi piacerebbe capire qual è l'implicazione di quel fraseggio, perché temo di aver frainteso qualcosa.

Da Learn You a Haskell , il seguente paragrafo è il terzo e l'ultimo contenente "assumiamo *".

data Barry t k p = Barry { yabba :: p, dabba :: t k }  

E ora vogliamo renderlo un'istanza di Functor. Functorvuole tipi di tipo, * -> *ma Barrynon sembra che abbia quel tipo. Di che tipo è Barry? Bene, vediamo che ci vogliono tre parametri di tipo, quindi sarà something -> something -> something -> *. È sicuro dire che pè un tipo concreto e quindi ha una specie di *. Perché k, supponiamo *e quindi per estensione, tha una specie di* -> * . Ora sostituiamo questi tipi con quelli somethingche abbiamo usato come segnaposto e vediamo che ha una specie di (* -> *) -> * -> * -> *.

Perché stiamo assumendo qualcosa? Dopo aver letto "assumiamo X (cioè supponiamo che X sia vero)" è naturale per me pensare che dovremmo considerare anche il caso in cui X è falso. Nel caso specifico dell'esempio, non potrebbe tessere di tipo (* -> *) -> *e kdi tipo (* -> *)? Se questo fosse il caso, qualunque sia te kin realtà erano, t ksarebbe ancora un tipo concreto, no?

Vedo che l'intera linea di ragionamento viene quindi verificata rispetto al compilatore, ma non credo che il compilatore presuma . In tal caso, vorrei sapere cosa, in caso contrario, temo di perdere il significato del paragrafo.


4
Hai ragione. In effetti, possiamo avere k :: Lper qualsiasi tipo L, purché t :: L -> *. Un compilatore qui deve tuttavia scegliere alcuni specifici Lo ricorrere a un poligono. Un poligono sarebbe l'opzione più generale, ma qui GHC sceglie L = *(l'Haskell di base non ha poligami, devono essere attivati ​​come estensione). Poiché sceglie qualcosa che è piuttosto arbitrario, LYAH usa la parola "assume" (AFAICT).
chi,

1
Ok, forse il compilatore presume che mi avrebbe confuso almeno meno di quanto pensiamo , o per niente.
Enrico Maria De Angelis,

Risposte:


19

In effetti, il compilatore assume! Ma puoi chiederlo di non farlo con l'estensione PolyKinds. Puoi leggerlo più in dettaglio qui . Con tale estensione attivata, il tipo di Barrysarà forall k. (k -> *) -> k -> * -> *.


-1

Buon punto. L'autore fa un'ipotesi inutile. Forse solo per renderlo più facile da capire nel suo capitolo Tipo Foo, ma persone come te possono legittimamente metterlo in discussione.

Entrambi t, ke psono variabili di tipo. Come possiamo vedere yabba :: p, può vivere da solo, quindi è come una funzione costante, come se fosse un valore anziché un tipo, direbbe la firma del tipo Into Char, qualunque cosa ... lo chiami. Ma dal momento che è un tipo, allora è la firma gentile *.

Comunque tdigitare qui prende una variabile di tipo kper costruire un tipo ( dabba :: t k) quindi siamo sicuri che (nessuna ipotesi qui) tha una firma gentile come * -> *e kha* .

Una volta che lo sappiamo ... la Barry t k pfirma gentile del tipo è (* -> *) -> * -> * -> *che significa che ci vuole tallora ke poi pe ci dà il Barrytipo.

Modifica Assicurati di leggere il commento di @ luqui di seguito.


7
knon è vincolato ad essere *come lo affermi mentre lo deduci t. Potremmo avere k :: * -> *e t :: (* -> *) -> *, per esempio. Aggiungi un campo doo :: k Intal record e passerà senza problemi.
Luqui,

@luqui .. Sì hai ragione ... Non eliminerò questa risposta poiché il tuo commento è davvero degno di nota.
Redu,
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.