J'ai un problème de taper des fonctions anonymes à Haskell. Par exemple, lorsque nous avons:
\f -> f x
3 Réponses :
Voici trois façons équivalentes d'écrire votre première fonction: Notez que cette fonction, quelle que soit la syntaxe que vous utilisez dans sa définition, est une fonction de second ordre. Cela signifie que son argument, de sorte que cela nous donne le type d'argument de votre fonction: Notez également que vous pouvez utiliser des noms minuscules que vous souhaitez, tant pour le paramètre que pour les variables de type. Ainsi, vous pouvez aussi bien avoir écrit x code> est lui-même une fonction. C'est-à-dire que
x code> doit avoir un type de formulaire
x :: contraint1 t1, contrainte2 t2 => t1 -> t2 code>. Plus spécifiquement,
x code> doit accepter
5 code> comme premier (et éventuellement seulement) argument. Mais c'est la seule contrainte inhérente à son argument.
5 :: num t1 => t1 code>, donc
x :: num t1, contrainte2 T2 => T1 -> T2 code>. Il n'y a pas de contrainte inhérente à la valeur de retour de
x code>, de sorte que le type le plus général (permissive) est donc
x :: num t1 => t1 -> t2 code>. P >
\ x -> x 5 :: num t1 => (T1 -> T2) ->? code>. Mais qu'en est-il du type de retour? Eh bien, votre fonction s'applique simplement
x code> à 5 et évalue vers (renvoie) le résultat, de sorte que votre fonction renvoie le même type que
x code>. En supposant que votre fonction puisse accepter toute fonction possible
x code>, son type est donc
\ x -> x 5 :: num t1 => (T1 -> t2) -> T2 code>. P>
\ fonction -> fonction 5 :: num cinq => (cinq -> résultat) -> résultat code>. P> p> p>
Vous pouvez également choisir des types plus restrictifs. Par exemple, vous pouvez définir la version plus spécialisée de votre fonction comme: \ fonction -> fonction 5 :: (flotteur -> string) -> chaîne code>
>> Comment pouvons-nous obtenir ces types? em> Ces types sont ce que le système HASKELL peut déduire de la seule chose qu'elle a, c'est la définition donnée par l'utilisateur, telle que " x 5 ". p> L'important n'est pas que la fonction est anonyme. C'est que la fonction est donc, exactement Même type pour les versions anonymes et nommées. P> Bien sûr, vous pouvez être plus spécifique: p> haskell ne vous oblige pas à tout taper explicitement.
Il prend toutes les informations de frappe explicites (telles que pour F4) et les informations de frappe implicites produites par vos définitions et vos appels vers des fonctions de la bibliothèque, en tant que contraintes de frappe. P> Si les contraintes peuvent être résolues sans ambiguïté, bien; Cela s'appelle Type Inference em> comme mentionné par chi em> ci-dessus. Sinon, si les contraintes de frappe sont contradictoires ou ambiguës, l'exécution aborde. P> p>
Okey, ça aide beaucoup ... mais si nous avons une expression comme; \ x -> f x y code>. Comme je comprends bien, c'est la même chose que Func x = x y non? Comment pouvons-nous taper celui-ci quand y n'est même pas un argument ici ...
@ heisenberg7584 correct, le système refuse de donner un type pour \ x -> f x y jusqu'à ce que vous ayez défini F et Y. En théorie, peut-être que cela pourrait dire quelque chose comme (F :: T1-> T2-> T3) => T1-> T3 mais ne peut pas être dérangé. Mieux vaut sûr que désolé je suppose.
Désolé, juste du dernier. Alors suis-je raison que lorsque nous avons \ y -> x + y le type est num a => a -> A => a -> a code> car sur le côté gauche de l'expression, il y a juste y donc comme un x nous mettons Une certaine constante par exemple x = 3. Nous supprimons donc une partie du type (+) car x est une constante ici. Au cas où notre expression était \ xy -> x + y, nous n'avons aucune constance ici, le type serait donc
num A => a -> a -> a code> et sur le type d'autre de
g = x + y code> est juste num A => A Quelque X et Y sont juste en train de supposer qu'ils sont des nombres corrects?
@ Heisenberg7584 Fondamentalement d'une manière très simple si vous avez une expression comme \ x -> f x y le résultat du type est A -> B où A est un type de x et b est le type d'expression entière f x y
@ heisenberg7584 Si, sous GHCI, vous demandez ": T 4", puis ": T (+)", vous verrez que 4 n'a pas de type, juste une contrainte de type de num A i> ; Le signe + a "num A => A-> A-> A", ce qui signifie que + force ses deux opérandes et son résultat d'avoir le même type (numérique). Donc, dans une expression telle que x + 4, la sorte de signe + étend la contrainte de type de 4, num, à l'autre opérande, x. Vous ne pouvez donc pas ajouter un Int et un double sans utiliser un opérateur de conversion explicite. Et "\ x y -> x + y" a la même contrainte de type que + parce que c'est essentiellement la même chose que +. J'espère que ça t'as aidé.
Je pense que vous vous en compliquez de manière à ne pas avoir à. Fondamentalement Nous devons trouver le type de x que nous connaissons est une fonction qui a un argument de type appartenant à la typlass donc et voici notre réponse: p> La même situation est avec le dernier: < / p> f est encore une fois une fonction, mais cette fois, nous ne connaissons pas le type de son argument p> donc et encore - C'est ici, nous avons un type d'expression à gauche de -> code> symbole, puis le type d'expression entière sur Le droit de la flèche
-> code> strong>. Base sur votre exemple:
num code>, et renvoie un peu de type inconnu - disons
t code>: p>
x code> fonction renvoie quelque chose de type
t code>: p>
A code> est le type de
x code> et l'expression entière sur la droite renvoie
B code> p>
-> code> et à droite. p>
... Sauf que \ f -> f x code> n'a pas de type.
Il a. Nous supposons que x est le type d'α. X est un argument de la fonction F, donc f :: α -> β. β est le type de résultat de la fonction f. Alors résumant que nous obtenons (\ f -> f x) :: (α -> β) -> β
Je ne peux pas comprendre quel est le problème ici, mis à part un générique "Je ne comprends pas comment fonctionne le type d'inférence", qui est trop large. Peux-tu être plus précis?
@chi Un problème est fondamentalement ces exemples donnés, leur évaluation de leurs types afin que les résultats donnés soient calculés.
@ heisenberg7584 Vous avez donné les types là-bas. Quel problème spécifique i> avez-vous de comprendre pourquoi ces types sont corrects? Veuillez modifier votre question pour ajouter ces informations.
@Ajfarmar Edit FAIT
Dupliqué possible: Quelle partie de Hindley-Milner ne comprenez-vous pas? . Si ce n'est pas un duplicata, parlez de pourquoi.
Il n'y a rien de spécial ici sur les fonctions étant anonymes.
func x = x 5 code> est la même fonction exacte que votre première, et a donc le même type.
Et cette fonction prend son argument et l'applique à 5, de sorte que l'argument doit être une fonction qui prend un numéro, puis la fonction globale renvoie le type de retour de l'argument de fonction. Ceci est parfaitement logique et exactement ce que la signature de type vous dit - s'il vous plaît expliquer davantage la partie où vous avez du mal à comprendre.