OCamel inferenza tipo con funzioni di ordine superiore

BoG3
Ciao di nuovo,
vorrei porvi un altro mio dubbio:

date le seguenti funzioni:

let double n = n*2;; (* int -> int *)
let comp (f, g) = function x -> f(g x);;  (* ('a -> 'b) * ('c -> 'a) -> 'c -> 'b *)

mi chiede di determinare il tipo di
comp(double, double);;


io ho pensato:
dato che double : int -> int allora la funzione comp prende in input 2 funzioni entrambe int -> int !
quindi partendo da
let comp (f, g) = function x -> f(g x);;   
('a -> 'b) * ('c -> 'a) -> 'c -> 'b
e sostituendo int -> int a ('a -> 'b) e ('c -> 'a) ottengo:
let comp (double, double) = function x -> f(g x);;  
(int -> int) * (int -> int) -> int -> int
Giusto? La soluzione propposta è
comp(double, double): int->int


Come mai?

Risposte
apatriarca
Ogni volta che passi un argomento ad una funzione devi togliere il corrispondente "pezzo" dal tipo della funzione. Per cui, se double ha tipo int -> int, double 3 avrà tipo int. Nel tuo caso hai passato (double, double) a comp per cui rimane solo il resto del tipo, cioè int -> int. In effetti quella funzione è uguale a function x -> double ( double x) cioè a function x -> 4*x che come vedi è una funzione che prende un intero e ne restituisce un altro.

BoG3
Ciao,
fammi capire...
in pratica, siccome double è una funzione int->int, deve restituire un int, quindi qualunque altra funzione che riceva in pasto double
(f(double))
come input avra' int. A sto punto posso dire che f è int->int. Sarebbe giusto dire che f: int->int->int?

Poi vorrei chiederti come funzion l'associativita', ovvero:
let somma a b = a+b;;

se io richiamo somma 3;;

a cosa si va a sostituire 3?? ad a o b? che tipo di associativita' ha? a destra o sinistra?

Grazie mille

apatriarca
Partiamo dalla seconda. Gli argomenti vengono sempre passati da quello più a sinistra a quello più a destra nel caso di funzioni "normali". Quindi quando scrivi somma 3;; stai sostituendo il 3 al posto di a.

Nel primo punto stai invece facendo confusione. Se f prende come argomento double, allora non avrà come input un int, ma una funzione int -> int. Quindi il tipo è f : (int -> int) -> 'a. Ma una volta che associ qualcosa ad un argomento questo non è più un argomento della funzione e quindi devi togliere il corrispondente pezzo dal tipo. Nel caso sopra di somma a b per esempio, se scrivi somma 3 ti rimane un solo argomento da passare (b) e quindi il tipo dovrà essere int -> int.

BoG3
"apatriarca":

Nel primo punto stai invece facendo confusione. Se f prende come argomento double, allora non avrà come input un int, ma una funzione int -> int. Quindi il tipo è f : (int -> int) -> 'a.

Si, era quello che intendevo dire all'inizio ma credo di essermi espresso (molto) male.
"apatriarca":

Ma una volta che associ qualcosa ad un argomento questo non è più un argomento della funzione e quindi devi togliere il corrispondente pezzo dal tipo. Nel caso sopra di somma a b per esempio, se scrivi somma 3 ti rimane un solo argomento da passare (b) e quindi il tipo dovrà essere int -> int.


Tutto chiaro. Gentilissimo, grazie.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.