11
votes

Est-il possible de définir le type avec des objets appelables à Haskell?

Je suis assez nouveau à Haskell et pas trop à l'aise avec son système de type. Et je me demande s'il est possible de définir le type (DataType?), Les instances peuvent être appelées comme des fonctions?

analogues sont xxx

méthode en python ou en classe Méthode xxx

en C ++. (Plus d'exemples sont donnés dans Wikipedia pour le mot "objet de fonction").

L'exemple d'application d'une telle construction est polynom. L'objet est défini par la liste de ses coefficients, c'est-à-dire que je voudrais avoir de type comme celui-ci: xxx

maintenant, je peux définir la fonction xxx

(Ici, je ne me dérange pas, pour pouvoir appeler Polynom avec des coefficients d'into sur des flotteurs ... il est juste des détails techniques)

maintenant je peux l'appeler sur mon polinomial ( Invite interactive): xxx

mais de cette façon n'est pas trop fantaisie. Est souhaitable d'être capable d'appeler polynôme directement comme xxx

de sorte que la question est la suivante: il est possible de définir un tel type polynomial, que des objets (instances) peuvent être appelés (d'occasion). comme des fonctions)? Peut-être que ce modèle peut être mis en œuvre d'une autre manière, sans impliquer les "données"? Peut-être que certains jouent avec des types de fonctions ou de la SMTH. sinon?

Bien sûr, cette idée peut être appliquée non seulement aux polynômes. En fait, à n'importe quelle fonction, qui doit "avoir du type" et a "certaines données jointes" (en cas de polynôme - il est coefficients).

ou si cela n'est pas possible, il y a une raison spécifique. Pour cela ou ce n'est tout simplement pas pris en charge?

PS: Il me semble que cette approche directe (comme décrit ci-dessus) est impossible, car être appelable mypoly doit être de type (INT -> INT). Mais tapez (int -> int) ne peut avoir aucune donnée jointe (i.g. coefficients polynomiaux). Mais je veux m'assurer que j'ai raison.


4 commentaires

Qu'est-ce qui ne va pas avec let mypoly = callpoly (polynôme [1, 2, 3]) ?


Pourquoi ne pas simplement inventer votre propre application polynomiale 'Sytax', par ex. [] ||| x = 0; (C: CS) ||| x = c + x * (CS ||| x) dans GHCI Vous demandez [1,2,3,4,5] ||| 3 et obtenir 547 comme réponse.


Voir: Stackoverflow.com/Questtions/6482970/...


@shang merci. Le dernier lien est exactement ce que je cherchais. Désolé, je ne l'ai pas trouvé moi-même.


3 Réponses :


4
votes

Je peux me procurer ma terminologie ici, car je ne suis pas un vétéran Haskell moi-même. Cependant, de ma compréhension de Haskell:

Comme HASKELL n'est pas orientée objet, il n'a pas d'objet ni d'instances (au sens traditionnel, c'est-à-dire). Au lieu d'instances d'un type de données, vous avez des valeurs du type de données. Cela étant dit, car les fonctions sont des données (valeurs) comme des entiers et des chaînes, vous pouvez avoir des valeurs appelables en ce sens qu'ils peuvent porter leur propre contexte (comme une instance dans OO World).

Si votre objectif est d'avoir une valeur que vous transmettez, cela porte le polynom A , vous pouvez simplement évaluer partiellement votre fonction callpoly , puis pensez de cela comme votre "polynome appelable". Exemple: xxx

MAINTENANT, le type de CallMypoly est le suivant: xxx

et vous pouvez l'appeler comme ceci: xxx

équivalent à: xxx


1 commentaires

Le type de CallMypoly n'est que polymorphe si le monomorphisme ne s'applique pas. Si vous définissez CallMypoly comme indiqué, le MR s'applique (s'il n'est pas désactivé par -xnomonomorphistressrections ou pragmes). Pour obtenir le type polymorphique, 1) Donner une signature de type 2) Bind avec un argument, CallMypoly X = CallPoly MyPoly X ou 3) Désactiver M.



4
votes

Oui, dans HASKELL, vous ne pouvez pas avoir d'objets appelables car cela gâcherait beaucoup l'inférence de type. Vous devrez donner des noms explicites à vos fonctions, comme dans les langues oo qui ne prennent pas en charge __ appel __ et nécessitent des noms de méthodes explicites.

D'autre part, une application partielle de la fonction et des fermetures le font. Très facile à obtenir une fonction polynomiale d'une représentation polynomiale de sorte que la limitation n'est pas si mauvaise. xxx


0 commentaires

8
votes

C'est bien que vous soyez familiarisé avec le concept de "objet de la fonction" C ++, car c'est une bonne introduction à l'idée de Haskell de ce que vous pouvez faire avec des fonctions anciennes ... précisément, curry, application partielle et travaux de passage comme des arguments à d'autres fonctions.

en C ++, votre code ressemblerait à quelque chose comme: p> xxx pré>

Ceci est fondamentalement exprimant une seule fonction pure: un évaluateur polynomial qui prend une liste de coefficients et une valeur. Cela pourrait tout aussi facilement être exprimé en C ++ comme suit: p> xxx pré>

mais ce formulaire n'est pas curry em> comme le formulaire précédent est. La bonne chose à propos de la forme au curry est que vous pouvez dire: p> xxx pré>

au lieu de: p> xxx pré>

ok. Nous pensons donc à cet "objet de fonction" en tant que concept de programmation orienté objet - un objet qui masqueurs en tant que fonction - mais oublions les objets maintenant. Si vous le regardez à Haskell, il s'agit simplement d'une fonction et ne nécessite aucun type de données défini par l'utilisateur pour exprimer joliment: p> xxx pré>

Vous pouvez l'appeler "normalement" (comme avec évaluatepolynomial () code> ci-dessus), appliquez-le sur les deux arguments à la fois: p> xxx pré>

mais parce que les fonctions HASKELL sont curreuses, vous pouvez appliquer partiellement (comme Avec le Objet de fonction Polynôme Code>): P>

do
  let (P p) = mkPolynomial [1, 2, 3]
  print (p 4)
  print (p 5)
  print (p 6)


4 commentaires

Merci pour ce tutoriel. L'idée est belle. Mais je pense toujours au style oo. Avec votre solution, je ne comprends pas, comment définir d'autres opérations (ajouter, différencier, etc.) et celles-ci devraient être polymorphes. Par exemple. Je peux soit avoir des splines, soit appelables, soit une addition, une différenciation, etc. Je ne peux pas comprendre, comment adopter votre solution à ce cas. Le problème est que dans P, nous avons perdu des informations sur les coefficients (qui, dans ma compréhension, devraient être encapsulées en objet polynomial).


Eh bien, si vous voulez, vous pouvez définir nouveautype polynomial a = num a => p {coefficients :: [a]} et Evaluatpolynomial :: num A => Polynôme a -> A - > A . Ceci est essentiellement la même chose que votre définition initiale. Mais c'est aussi la même chose que la mienne, avec juste un peu de sucre supplémentaire de type. Vous pouvez toujours dire laisser p = évaluatepolynomial (p [1, 2, 3]) ou autre.


Cela a toujours le même problème (que j'essaie de résoudre dans ces questions): la valeur, qui a des informations sur les coefficients et la valeur, qui est la fonction est distincte (elles sont liées à différentes variables). Mais je veux que ceux-ci soient les mêmes. Dans ce cas, il est plus agréable (IMHO) de définir de classe appelable a ... avec une opération infixe comme (|||) :: (A int) -> int -> int et mettre en œuvre cette opération pour le polynôme. Puis appelez-le comme let y = mypoly ||| x (cette solution a été proposée dans d'autres réponses). Quoi qu'il en soit, merci pour vos commentaires.


La classe appelable que vous proposez existe déjà comme catégorie . Il existe également un type de données pratique qui existe quels modèles catégorie joliment: (->) . Votre infixe (|||) est identique à celle de mon fonction polynomial ci-dessus. C'est-à-dire que j'aurais pu l'appeler (|||) et a donc été capable d'écrire [1, 2, 3] ||| 4 . Point est que les solutions sont identiques; J'essaie de vous aider à vous éloigner de la pensée de OO qui complique uniquement le problème.