Question
J'ai une question concernant deux types int -> (int -> int) et (int -> int) -> int. Quelle est la différence entre ces deux-là?
J'ai lu ici quelque part que le premier pourrait être interprété comme une fonction qui prend un INT et renvoie une fonction qui prend et INT et renvoie un int, qui est le même que int -> int -> int. Est-ce correct?
La solution
La différence entre int -> (int -> int)
et int -> int -> int
est négligeable (vous ne vous soucieriez vraiment que si vous deviez vous interopérer avec une autre langue). Ce sont des fonctions au curry qui prennent efficacement deux entiers et renvoient un entier (par exemple, l'opérateur d'addition intégré a un type dans ce sens).
Cependant, ces deux sont très différents de (int -> int) -> int
, qui prend un fonction Des entiers aux entiers et renvoie un entier. Comme d'autres l'ont mentionné, le seul exemple simple d'une telle fonction appliquerait la fonction donnée à une valeur spécifique (par exemple fun (f:int->int) -> f 13
).
Autres conseils
Bonne question, je soupçonne que fonctionnellement il n'y a pas beaucoup de différence. J'ai passé un certain temps à jouer pour essayer de trouver comment même obtenir ces deux signatures. (John Palmer let fun1 i = fun j -> i + j
donne juste int -> int -> int
pour moi)
let add a b = a + b // int -> int -> int
let inc a = add a // int -> (int -> int)
Je ne pouvais pas penser à un exemple non contrôlé pour la deuxième signature:
let foo fn : int -> fn 1 // (int -> int) -> int
(Cela ne répond pas directement à votre question, mais peut donner à quelqu'un d'autre quelque chose à mâcher)
Je ne connais pas vraiment F #, mais cela semble assez intuitif (beaucoup d'autres langues ont les mêmes notions).
- Est une fonction qui prend un int, et renvoie une fonction qui prend un int et renvoie un int
- Est une fonction qui prend une fonction qui prend un int et renvoie un int, et renvoie un int
Le premier serait un peu comme une fonction au curry.
Voyons donc à quoi ressembleraient les implémentations:
première
let func1 i = fun j -> i+j
Cela a une signature de int -> (int -> int)
Notez que func1 2 3
ne devrait pas fonctionner
ÉDITER: Il s'avère qu'en raison de la façon dont l'association fonctionne, c'est en fait bien
Mais c'est différent de
let func2 i j= i+j
qui a un type de int -> int -> int
ici func2 1 2
c'est bien
L'autre exemple que nous pouvons créer comme ceci:
let func4 a = a 1
Cela aura une signature de ('t->int) -> u
Choisir un béton a
marchera. Notez que func4 1 2
ne compilera certainement pas