10
votes

Pourquoi la somme x y est de type (num a) => A -> A -> A à haskell?

J'ai lu sur Haskell et j'ai du mal à comprendre comment les définitions de la fonction sont traitées dans cette langue.

Disons que je définissais un somme Fonction: xxx

si je demande HASKELL pour son type xxx

i get xxx < ol>

  • Qu'est-ce que cela signifie que l'opérateur => ? At-il quelque chose à voir avec les expressions de Lambda? C'est comme ça que l'on signale que ce qui suit l'opérateur => est un, en C #.
  • Qu'est-ce que le a -> a -> a signifie? Par inspection des yeux sur plusieurs fonctions que j'ai essayé, il semble que les arguments a -> a sont les arguments et la finale -> A est le résultat de la fonction de somme. Si cela a raison, pourquoi pas quelque chose de (a, a) -> A , qui semble plus intuitif?

  • 1 commentaires

    Si vous voulez comprendre HASKELL, vous feriez mieux d'obtenir une (bonne) introduction au lieu de demander à chaque partie de la langue. Stackoverflow.com/Questtions/1012573/how-to- Learn-Haskell / ... liens vers quelques bonnes ressources et dispose de nouveaux conseils.


    5 Réponses :


    4
    votes

    C'est a -> A -> A plutôt que (a, a) -> A, un à cause de Currying . Faire de plaisir: Currying était (re) inventé par Haskell Curry! Fondamentalement, cela signifie que si vous fournissez un argument unique, vous récupérerez une autre fonction de type a -> A , une application partielle de la somme.


    7 commentaires

    Même après avoir lu l'intro de l'article de Wikipedia, je ne peux pas obtenir quel est le point de currying :(


    Je n'ai pas le point non plus! C'est juste une de ces choses que vous faites dans la programmation fonctionnelle ...


    Vous curry fonctionne afin que vous puissiez les appliquer partiellement. Voulez-vous ajouter 3 à chaque élément d'une liste? Aucun problème! - Carte (+3) [1, 2, 3, 4, 5]


    @Paul Harvey: En fait, carte (+3) est un mauvais exemple d'application partielle, c'est vraiment un. Section de l'opérateur. mappe ((+) 3) est une application partielle.


    Si vous avez la fonction "SendMessage pour taper le contenu" et que vous envoyez souvent des messages d'état numériques sur "Server", vous pouvez créer une fonction d'assistance avec application partielle: "SendStatus = SendMessage Server Number" et l'utiliser comme "SendStatus 10".


    @Matajon: à Haskell L'application partielle d'un opérateur d'infixe est appelée section, oui. C'est une demande toujours partielle cependant.


    Une autre façon d'y penser: que signifie "plus 1"? Une fonction entièrement conforme à celle-ci qui lie l'une des entrées à 1. La capacité de générer de nouvelles fonctions existantes, même des familles entières de nouvelles fonctions, à travers des opérations élémentaires telles que des applications partielles, est le point.



    5
    votes

    num a => signifie "dans ce qui suit, A doit se référer à un type d'une instance de type tyclass num " ( qui est un peu comme une interface pour les types de nombres).

    Le => L'opérateur sépare les "contraintes de clastographie" du "corps" du type. C'est un peu comme le opérateur pour des contraintes génériques dans C #. Vous pouvez le lire comme une implication logique comme "si a est un type numérique, alors somme peut être utilisé avec type a -> a -> A -> a ".

    a -> a -> a signifie "une fonction qui prend un a et renvoie une fonction qui prend un a et renvoie un a ". Pour ce faire, vous devez comprendre que somme x y analyse comme (somme x) y .

    En d'autres termes: vous appelez d'abord somme avec l'argument x . Vous récupérez ensuite une nouvelle fonction de type a -> A . Vous appelez ensuite cette fonction avec l'argument y et vous récupérez maintenant une fonction de type A , où a est le type de x et y et doit être une instance du type Typeclass.

    si vous voulez somme pour avoir type num a => (a, a) -> a , vous pouvez le définir comme somme (x, y ) = x + y . Dans ce cas, vous avez une fonction qui prend un tuple contenant deux A s et renvoie un a (où a est à nouveau une instance de < code> num tyteclass).

    Cependant, le "style de curry" (fonctions renvoyant des fonctions pour simuler plusieurs paramètres) est beaucoup plus souvent utilisé que le style de tuple, car il vous permet d'appliquer facilement partiellement des fonctions. Exemple carte (somme 5) [1,2,3] . Si vous aviez défini somme avec un tuple, vous devez faire carte (\ y -> somme 5 y) [1,2,3] .


    0 commentaires

    10
    votes

    Ceci est parce que

    Chaque fonction de haskell prend un paramètre un seul paramètre et renvoie un valeur unique

    Si une fonction doit prendre plusieurs valeurs, la fonction aurait été une fonction au curry ou qu'il doit prendre un single tuple .

    Si nous ajoutons des parenthèses, la signature de fonction devient : xxx

    in haskell, la signature de fonction: a -> b signifie une fonction "Domaine" de la fonction est a < / code> et la "codomaine" de la fonction est b ; Ou dans la langue d'un programmeur, la fonction prend un paramètre de type A et renvoie une valeur de type B .

    par conséquent, la définition de la fonction Somme :: Num -> (Num -> Num) MOYEN est "Une fonction qui prend un paramètre de type a et renvoie une fonction de type num -> num ".

    En effet, cela conduit à la fonction de curry / partielle.

    Le concept de Currying est essentiel dans des langages fonctionnels comme Haskell, car vous voudrez faire des choses comme: xxx

    dans ce code (somme 5 ) est une fonction qui prend un seul paramètre, cette fonction (somme 5) sera appelée à chaque élément de la liste, par exemple ((somme 5) 1) renvoie 6.

    si Somme avait une signature de somme :: (num, num) -> num , puis La somme devrait recevoir tous les deux paramètres en même temps car la somme est une "fonction qui reçoit un tuple (num, num) et renvoie un numéro".

    maintenant , la deuxième question, qu'est-ce que num a => a -> a signifie? C'est fondamentalement un raccourci pour dire que chaque fois que vous voyez a dans la signature, remplacez-le par num ou avec l'une de sa classe dérivée.


    1 commentaires

    Vous abusez un peu la notation: num est une typlass, pas un type.



    4
    votes

    La documentation Haskell n'est pas trop claire à ce sujet, mais (num a) => signifie que la fonction fonctionne pour tous les cas où a est un numéro ou en dérive (donc est un nombre).

    Voir aussi: http: //www.cse.unsw .edu.au / ~ EN1000 / HASKELLL / INBUILT.HTML


    0 commentaires

    29
    votes

    0. strong> Le haskell => code> n'a rien à voir avec C # 'S => code>. In Haskell une fonction anonyme est créée avec xxx pré>

    également, ne nommez pas la fonction somme code> car Une telle fonction existe déjà en prélude. Appelons-le plus code> à partir de maintenant pour éviter la confusion. P>

    1. Strong> de toute façon, le => code> in haskell fournit un contexte au type. Par exemple: p> xxx pré>

    ici, le Afficher a => code> signifie A code> type doit être une instance de Classe de type em> Afficher code>, ce qui signifie A code> doit être convertible à une chaîne. De même, (num a) => A -> A -> A code> signifie que le type A code> doit être une instance du numéro de classe de type, ce qui signifie a doit être comme un numéro. Cela met une contrainte sur A code> de sorte que montrez code> ou plus code> n'acceptera pas une entrée non prise en charge, par ex. plus "56" "ABC" code>. (La chaîne n'est pas comme un nombre.) P>

    Une classe de type est similaire à celle de C #, ou plus spécifiquement, un CONTRAINT DE TYPE DE BASE D'INTERFACE EN GENRES . Voir la question Expliquer les classes de type à Haskell em> pour plus d'informations . P>

    2. strong> a -> a -> a code> signifie a -> (a -> a) code>. Par conséquent, il s'agit en fait d'une fonction unaire qui renvoie une autre fonction. P>

    plusFourToList = \l -> map(\y -> plus(4,y), l) 
    


    3 commentaires

    Une bonne réponse, sauf que je crains toujours lorsque j'entends quelqu'un dire que les classes de types sont comme des classes d'interface. Ils ont un rôle quelque peu analogue, mais le raisonnement de cette analogie vous évitera sérieusement. En particulier dans HASKELL, une classe de type n'est pas elle-même un type, vous ne pouvez donc pas écrire "[NUM]" pour signifier une liste de chiffres.


    Bien que l'écriture (num a) => [A] n'est pas vraiment si différente. Je crois, tant que vous précisez que l'analogie de l'interface est simplement une simple pour vous aider à démarrer, c'est bon.


    Même si c # avait une interface num , quelque chose comme list est toujours très différent de (num a) => [a] , Parce que [5 :: int, 3.5 :: double] n'est pas une valeur valide de type (num a) => [a] in haskell. Je pense que cela surprend beaucoup de gens quand ils voient d'abord des classes de type.