Funzione ML di tipo 'a ->' b


19

Il nostro professore ci ha chiesto di pensare a una funzione in OCaml che ha il tipo

'a -> 'b

cioè una funzione di un argomento che potrebbe essere qualsiasi cosa e che può restituire qualsiasi cosa diversa.

Ho pensato di usare raiseuna funzione che ignora il suo argomento:

let f x = raise Exit

Ma il professore ha detto che c'era una soluzione che non richiede alcuna funzione nella libreria standard. Sono confuso: come puoi fare un 'bse non ne hai uno in primo luogo?

Sto chiedendo qui piuttosto che su Stack Overflow perché voglio capire cosa sta succedendo, non voglio vedere solo un programma senza spiegazioni.


2
Si prega di indirizzare la programmazione dell'apprendimento degli studenti CS101 nella risposta, non il teorico dei tipi a cui la risposta potrebbe ispirarlo a diventare in seguito.
Gilles 'SO-smetti di essere malvagio' il

Sarebbe utile se spiegassi come hai capito che raiseavrebbe funzionato, quindi sappiamo come spiegare meglio perché la soluzione che il tuo prof sta cercando (che funzionerà per gli stessi motivi che raisefunzionano) funziona.
sepp2k,

@ sepp2k in raise : exn -> 'amodo da poter ottenere il valore restituito, ho semplicemente ignorato l'argomento.
Gilles 'SO-smetti di essere malvagio' il


Risposte:


18

Lo scheletro è let f x = BODY. In BODY devi usare x solo in modi generici (ad esempio, non inviarlo a una funzione che prevede numeri interi) e devi restituire un valore di qualsiasi altro tipo. Ma come può essere vera quest'ultima parte? L'unico modo per soddisfare l'istruzione "per tutti i tipi 'b, il valore restituito è un valore di tipo 'b" è assicurarsi che la funzione non ritorni. Esistono esattamente due possibilità: errori BODY o non si interrompe. La funzione non funziona raise, quanto segue non termina:

let rec f x = f x

19

Innanzitutto, alcune osservazioni. Utilizzando solo il calcolo lambda tipizzato core non è possibile ottenere 'a -> 'bperché il sistema di tipizzazione è in corrispondenza (tramite l' isomorfismo di Curry Howard ) con le logiche intuizionistiche e la formula corrispondente A → Bnon è una tautologia.

Altre estensioni come tuple e abbinamenti / condizionali conservano alcuni tipi di prodotto consistenza logica aggiungendo *che corrispondono alla connettivo logico e , e tipi di somma |che corrispondono al o . Ancora una volta, non aspettarti che producano quel 'a -> 'btipo, in quanto consentirebbe di provare una formula che non è una tautologia.

Quindi le tue uniche possibilità sono usare altre costruzioni che sfuggono alle logiche come raise(ma in questo caso non ti è permesso) ... o let rec! La ricorsione consente di creare programmi che non si interrompono mai e ai loro risultati può essere assegnato un tipo di ritorno arbitrario in quanto non verranno mai prodotti. Ora, se pensi alla funzione più banale non terminante (quella che si chiama direttamente per restituire un risultato):

let rec f x = f x

Noterai che il suo tipo è esattamente 'a -> 'b: qualunque sia l'argomento fornito, si può presumere che il risultato (che non verrà mai calcolato) abbia alcun tipo.

Naturalmente questa fnon è una funzione interessante, ma questo è il punto. In OCaml, qualsiasi funzione il cui tipo non assomiglia a una formula valida è una funzione sospetta.


Il richiedente non ha capito una parola dei tuoi primi due paragrafi, ma mi piace la tua frase "ai loro risultati può essere assegnato un tipo di ritorno arbitrario in quanto non verranno mai prodotti".
Gilles 'SO-smetti di essere malvagio' il

1

Usando una primitiva di compilatore puoi scrivere questo:

external magic: 'a -> 'b = "%identity"

(e in effetti la distribuzione del compilatore fornisce questo, sebbene non faccia parte del linguaggio). Questo è un cast di identità non sicuro.

Il tuo professore quasi certamente non lo vuole. Tuttavia, questa è anche l'unica funzione utile con il tipo di 'a -> 'bcui sono a conoscenza, e infatti viene utilizzata nella stessa distribuzione OCaml.

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.