Il controllo del tipo può essere reso decidibile arricchendo opportunamente la sintassi. Ad esempio, nel documento, abbiamo lambda scritto come \x -> e
; per digitare-verificare, è necessario indovinare il tipo di x
. Tuttavia, con una sintassi opportunamente arricchita, questo può essere scritto come \x :: t -> e
invece, che risolve il problema. Allo stesso modo, nel documento, consentono ai lambda di livello testo di essere impliciti; ovvero, se e :: t
, quindi anche e :: forall a. t
. Per eseguire il controllo ortografico, devi indovinare quando e quanti forall
aggiungere e quando eliminarli. Come in precedenza, si può fare questo più deterministico con l'aggiunta di sintassi: aggiungiamo due nuovi espressione forma /\a. e
e e [t]
e due nuova regola di battitura che dice che se e :: t
, poi /\a. e :: forall a. t
, e se e :: forall a. t
, quindi e [t'] :: t [t'/a]
(dove le parentesi in t [t'/a]
sono parentesi di sostituzione). Quindi la sintassi ci dice quando e quante forche aggiungere e quando eliminarle.
Quindi la domanda è: possiamo passare da Haskell a termini di sistema F sufficientemente annotati? E la risposta è sì, grazie ad alcune restrizioni critiche poste dal sistema di tipo Haskell. Il più critico è che tutti i tipi sono di prima scelta *. Senza entrare troppo nel dettaglio, "rank" è relativo al numero di volte che devi andare a sinistra di un costruttore ->
per trovare uno forall
.
Int -> Bool -- rank 0?
forall a. (a -> a) -- rank 1
(forall a. a -> a) -> (forall a. a -> a) -- rank 2
In particolare, questo limita il polimorfismo un po '. Non possiamo digitare qualcosa di simile con i tipi di rango uno:
foo :: (forall a. a -> a) -> (String, Bool) -- a rank-2 type
foo polymorphicId = (polymorphicId "hey", polymorphicId True)
La prossima restrizione più critico è che le variabili di tipo possono essere sostituite solo da tipi monomorfa. (Questo include altre variabili di tipo, come a
, ma non tipi polimorfi come forall a. a
.) Ciò garantisce in parte che la sostituzione di tipo conserva la rank-one-ness.
Si scopre che se si effettuano queste due restrizioni, quindi non solo è decidibile il tipo-inferenza, ma si ottiene anche minimo tipi.
Se passiamo da Haskell a GHC, possiamo parlare non solo di cosa è tipabile, ma di come appare l'algoritmo di inferenza. In particolare, in GHC, ci sono estensioni che rilassano le due precedenti restrizioni; in che modo GHC fa l'inferenza in quell'impostazione? Bene, la risposta è che semplicemente non ci prova nemmeno. Se vuoi scrivere termini usando queste caratteristiche, devi aggiungere le annotazioni di battitura di cui abbiamo parlato fino al paragrafo 1: devi annotare esplicitamente dove forall
s viene introdotto ed eliminato. Quindi, possiamo scrivere un termine che rifiuta il type-checker di GHC? Sì, è semplice: usa semplicemente tipi o impraticabilità di secondo grado non annotati (o superiori). Ad esempio, il seguente non digitare-controllo, anche se ha un tipo di annotazione esplicita ed è tipizzabile con rango di due tipi:
{-# LANGUAGE Rank2Types #-}
foo :: (String, Bool)
foo = (\f -> (f "hey", f True)) id
* In realtà, limitando di rango due è sufficiente a rendere decidibile, ma l'algoritmo per i tipi di rango uno può essere più efficiente. Classificare tre tipi già fornisce al programmatore una corda sufficiente a rendere il problema di inferenza indecidibile. Non sono sicuro che questi fatti fossero noti al momento in cui il comitato ha scelto di limitare Haskell ai tipi di grado 1.
Haskell utilizza un'edizione * resitricted * di System F denominata [* Hindley Milner *] [http://en.wikipedia.org/wiki/Hindley-Milner]. AFAIK è possibile dedurre il tipo di qualsiasi espressione che ha un tipo. Rendere impossibile il controllo dei tipi è una questione di attivare estensioni strane abbastanza. – fuz
@FUZxxl: Credo che abilitando solo 'RankNTypes' e' ImpredicativeTypes' si abbia tutta la potenza di System F (e poi alcuni, dato che Haskell supporta anche l'astrazione su operatori di tipo). –
Questo è quello che ho cercato di dire "Rendere impossibile il controllo dei tipi è una questione di accensione di estensioni strane". – fuz