Esempio conciso di costo esponenziale dell'inferenza di tipo ML


11

Mi è stato segnalato che il costo dell'inferenza di tipo in un linguaggio funzionale come OCaml può essere molto elevato. L'affermazione è che esiste una sequenza di espressioni tale che per ogni espressione la lunghezza del tipo corrispondente è esponenziale sulla lunghezza dell'espressione.

Ho ideato la sequenza qui sotto. La mia domanda è: conosci una sequenza con espressioni più concise che raggiunge gli stessi tipi?

# fun a -> a;;
- : 'a -> 'a = <fun>
# fun b a -> b a;;
- : ('a -> 'b) -> 'a -> 'b = <fun>
# fun c b a -> c b (b a);;
- : (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c = <fun>
# fun d c b a -> d c b (c b (b a));;
- : ((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
   (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'd
= <fun>
# fun e d c b a -> e d c b (d c b (c b (b a)));;
- : (((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
    (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'd -> 'e) ->
   ((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
   (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'e
= <fun>
# fun f e d c b a -> f e d c b (e d c b (d c b (c b (b a))));;
- : ((((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
     (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'd -> 'e) ->
    ((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
    (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'e -> 'f) ->
   (((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
    (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'd -> 'e) ->
   ((('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'c -> 'd) ->
   (('a -> 'b) -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'f
= <fun>

Risposte:


14

In questa risposta, mi atterrò a un frammento ML centrale della lingua, con solo lambda-calcolo e polimorfico letdopo Hindley-Milner . L'intero linguaggio OCaml ha funzionalità aggiuntive come il polimorfismo delle righe (che se ricordo bene non cambia la complessità teorica, ma con cui i programmi reali tendono ad avere tipi più grandi) e un sistema di moduli (che se colpisci abbastanza forte può essere non -terminante in casi patologici che coinvolgono firme astratte).

La complessità temporale peggiore per decidere se un programma ML di base ha un tipo è un esponenziale semplice nella dimensione del programma. I riferimenti classici per questo risultato sono [KTU90] e [M90]. Un trattamento più elementare ma meno completo è dato in [S95].

La dimensione massima del tipo del tipo di un programma ML di base è infatti doppiamente esponenziale nella dimensione del programma. Se il controllo del tipo deve stampare il tipo di programma, il tempo può quindi essere doppiamente esponenziale; può essere riportato a un semplice esponenziale definendo abbreviazioni per parti ripetute dell'albero. Ciò può corrispondere alla condivisione di parti dell'albero dei tipi in un'implementazione.

Il tuo esempio mostra una crescita esponenziale del tipo. Si noti, tuttavia, che è possibile fornire una rappresentazione di tipo lineare del tipo usando le abbreviazioni per parti ripetute del tipo. Ciò può corrispondere alla condivisione di parti dell'albero dei tipi in un'implementazione. Per esempio:

# fun d c b a -> d c b (c b (b a));;
t2 -> t2
where t2 = (t1 -> 'b -> 'c) -> t1 -> 'a -> 'd
where t1 = 'a -> 'b

Ecco un esempio concettualmente più semplice: la dimensione del tipo della coppia (x,x)è doppia rispetto alla dimensione del tipo di x, quindi se componi la pairfunzione volte, otterrai un tipo di dimensione .NΘ(2N)

# let pair x f = f x x;;
# let pairN x = pair (pair (pair … (pair x)…));;
'a -> tN
where tN = (tN-1 -> tN-1 -> 'bN) -> 'bN
…
where t2 = (t1 -> t1 -> 'b2) -> 'b2
where t1 = ('a -> 'a -> 'b1) -> 'b1

Introducendo letdefinizioni polimorfiche nidificate , la dimensione del tipo aumenta nuovamente in modo esponenziale; questa volta, nessuna quantità di condivisione può radere dalla crescita esponenziale.

# let pair x f = f x x;;
# let f1 x = pair x in
  let f2 x = f1 (f1 x) in
  let f3 x = f2 (f2 x) in
  fun z -> f3 (fun x -> x) z;;

Riferimenti

[KTU90] Kfoury, J .; Tiuryn; Urzyczyn, P. (1990). "La tipabilità ML è completa in tempo reale". Dispense in Informatica. CAAP '90 431: 206-220. [ Springer ] [ Google ]

[M90] Mairson, Harry G. (1990). "Decidere la tipabilità ML è completa per il tempo esponenziale deterministico". Atti del 17 ° simposio ACM SIGPLAN-SIGACT sui principi dei linguaggi di programmazione. POPL '90 (ACM): 382–401. [ ACM ]

[P04] Benjamin C. Pierce. Argomenti avanzati in tipi e linguaggi di programmazione. MIT Press, 2004. [ Amazon ]

[PR04] François Pottier e Didier Rémy. "L'essenza dell'inferenza di tipo ML". Capitolo 10 in [P04]. [ pdf ]

[S95] Michael I. Schwartzbach. Inferenza di tipo polimorfico. BRICS LS-95-3, giugno 1995. ps


quindi, in sostanza, la natura "compositiva" delle espressioni di tipo unita all'inferenza di tipo è la radice del problema?
didierc,

1
@didierc Non capisco il tuo commento. Molte cose sono composizionali. In un certo senso, la ragione fondamentale è che dalle operazioni di base di duplicazione di un oggetto (vincolo che due tipi siano uguali) e di accoppiamento (l' ->operatore), è possibile effettuare una crescita esponenziale (un albero di Fibonacci).
Gilles 'SO- smetti di essere malvagio' il

Sì, penso che sia quello che intendevo dire: l'algebra di tipo è per definizione compositiva (hai usato i termini "componi la funzione di coppia" nella tua risposta, è probabilmente lì che ho preso la parola), nel senso che le espressioni di tipo sono costruite da espressioni e operatori più piccoli, e ogni nuova composizione di espressioni ridimensiona la dimensione dell'espressione almeno di un fattore 2 (con tipi polimorfici più complessi - triadici o più, il fattore è più grande).
didierc,
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.