Question

Je pensais que je voudrais essayer modéliser une intégration numérique sur les quantités de vecteur de différentes dimensionnalité, et compris que les classes de type étaient la voie à suivre. Je besoin de quelque chose pour définir la différence entre les deux valeurs et mettre à l'échelle par un multiplicateur (pour obtenir le dérivé), ainsi que d'être en mesure de prendre la fonction de la distance.

Jusqu'à présent je:

class Integratable a where
    difference :: a -> a -> a
    scale :: Num b => a -> b -> a
    distance :: Num b => a -> a -> b

data Num a => Vector a = Vector1D a | Vector2D a a

instance Num a => Integratable (Vector a) where
    difference (Vector1D x1) (Vector1D x2) = Vector1D (x1 - x2)
    scale (Vector1D x) m = Vector1D (x * m)
    distance (Vector1D x1) (Vector1D x2) = x1 - x2
    difference (Vector2D x1 y1) (Vector2D x2 y2) = Vector2D (x1 - x2) (y1 - y2)
    scale (Vector2D x y) m = Vector2D (x * m) (y * m)
    distance (Vector2D x1 y1) (Vector2D x2 y2) = sqrt((x1-x2)*(x1-x2)
                                                      + (y1-y2)*(y1-y2))

Malheureusement, il y a quelques problèmes ici que je ne l'ai pas compris comment résoudre. Tout d'abord, la fonction scale donne des erreurs. GHC ne peut pas dire que m et x sont compatibles depuis la restriction de type rigide Num est donnée dans l'instance dans un cas, et dans le type de Vector dans l'autre ... Est-il possible de préciser que x et m sont les même type?

(je me rends compte, en fait, que même si x et m sont à la fois Num, ils ne peuvent pas être même Num. Comment puis-je le préciser? Si je ne peux pas le comprendre avec Num, en utilisant Double serait bien, mais je préfère le garder en général.)

Il y a un problème similaire avec distance. Toute tentative de préciser que le type de retour est Num échoue, car il ne peut pas dire dans la définition d'instance a va contenir des valeurs qui sont compatibles avec b.

Était-ce utile?

La solution

EDIT: Il me semble maintenant que l'article sur dépendances fonctionnelles de la HaskellWiki fournit les informations clés dans la meilleure forme que je peux trouver, alors je vous suggère la lecture qu'au lieu de ma réponse ici. Je ne suis pas enlever le reste du contenu, mais, comme il l'indique clairement (je l'espère) pourquoi IFD sont utiles ici.


Outre le regroupement de question des définitions qui a Dave sur ...

  

(je me rends compte, en fait, que même si x et m sont à la fois Num, ils ne peuvent pas être même Num. Comment puis-je le préciser? Si je ne peux pas le comprendre avec Num, en utilisant Double serait bien, mais je préfère le garder en général.)

Ceci est le principal problème, en fait. Vous ne pouvez pas multiplier un Integer par un Float, disons. En effet, vous avez besoin du x et m à l'échelle pour être du même type.

En outre, un problème similaire se pose avec la distance, avec la complication supplémentaire que sqrt a besoin d'un argument Floating. Donc, je suppose que vous auriez besoin de mentionner que quelque part aussi. (Très probablement sur l'instance, je suppose).

EDIT:. OK, car sqrt ne fonctionne que sur les valeurs Floating, vous pouvez rouler un pour ceux classe de types upCast Floats à Doubles en cas de besoin

Une autre idée consiste à avoir une Scalable de classe de types:

data Vector a = Vector1D a | Vector2D a a deriving (Show)                       

class Scalable a b | a -> b where
  scale :: a -> b -> a

instance (Num a) => Scalable (Vector a) a where
  scale (Vector1D x)   m = (Vector1D (x * m))
  scale (Vector2D x y) m = (Vector2D (x * m) (y * m))

Il utilise un soi-disant dépendance fonctionnelle dans la définition de Scalable. En fait, en essayant de se rappeler la syntaxe pour cela, j'ai trouvé ce lien ... Je suppose que vous devriez ne pas tenir compte de mon inférieur tentative d'être utile et lire les informations de qualité là-bas. ; -)

Je pense que vous devriez être en mesure d'utiliser pour résoudre votre problème d'origine.

Autres conseils

Pour fixer la deuxième erreur, je pense que vous devez réorganiser vos définitions dans la déclaration d'instance. D'abord les deux équations pour difference, puis les équations pour scale, alors à la fois pour distance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top