Question

Je suis en train de représenter les bords pondérés. Je veux éventuellement avoir oute être une instance de l'équation et Ord, avec la contrainte que ETYPE est une instance de l'équation et Ord. Supposons que j'ai fichier suivant que temp.hs:

data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype}

applyFunBy accessor ordfun = (\x y -> (ordfun (accessor x) (accessor y)))

instance Eq (OutE vtype etype) where
    --(==) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool
    --(/=) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool
    (==) = applyFunBy edgeValue (==)
    (/=) = applyFunBy edgeValue (/=)

quand je charge cela dans ghci, je reçois les erreurs suivantes:

temp.hs:10:19:
    Could not deduce (Ord etype)
      from the context (Eq (OutE vtype etype))
      arising from a use of `edgeValue' at temp.hs:10:19-27
    Possible fix:
      add (Ord etype) to the context of the instance declaration
    In the first argument of `applyFunBy', namely `edgeValue'
    In the expression: applyFunBy edgeValue (==)
    In the definition of `==': == = applyFunBy edgeValue (==)

temp.hs:11:19:
    Could not deduce (Ord etype)
      from the context (Eq (OutE vtype etype))
      arising from a use of `edgeValue' at temp.hs:11:19-27
    Possible fix:
      add (Ord etype) to the context of the instance declaration
    In the first argument of `applyFunBy', namely `edgeValue'
    In the expression: applyFunBy edgeValue (/=)
    In the definition of `/=': /= = applyFunBy edgeValue (/=)
Failed, modules loaded: none.

Si inclure les lignes pour les signatures de type pour (==) et (\ =), je reçois:

temp.hs:6:1:
    Misplaced type signature:
    == ::
      (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool

temp.hs:7:1:
    Misplaced type signature:
    /= ::
      (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool
Était-ce utile?

La solution

Vous etype limité à être Ord dans la défintion de OutE:

data (Ord etype) => OutE vtype etype = ...

Mais dans le cas Eq, vous êtes en train d'essayer de définir l'instance pour any etype sans restrictions.

instance Eq (OutE vtype etype) where

Bien sûr, cela ne fonctionne pas depuis OutE est lui-même vient d'être défini pour Ord etypes, donc vous devrez ajouter la contrainte à la définition classe de types d'instance ainsi.

instance (Ord etype) => Eq (OutE vtype etype) where

Notez qu'une définition soit == ou /= est suffisante pour le travail de classe de types.


Notez qu'il est souvent plus facile et donc mieux considérer le style de ne pas avoir des contraintes sur les types classe de types de data, mais juste sur les instances / méthodes qui nécessitent réellement la fonctionnalité membre de la classe.

Dans de nombreux cas, on n'a pas besoin de la contrainte et se termine juste avec les signatures de type inutilement maladroit.

Prenez par exemple un certain type de carte ordonnée Ord key => Map key value.

Et si nous voulons juste énumérer toutes les clés? Ou procurez-vous le nombre d'éléments? On n'a pas besoin des clés pour être Ord pour ceux-ci, alors pourquoi ne pas simplement laisser la carte sans restriction avec de simples

getKeys :: Map key value -> [key]
getLength :: Map key value -> Int

et juste ajouter la classe de types quand nous en avons besoin dans une fonction comme

insert :: Ord key => key -> value -> Map key value

Autres conseils

data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype}

Le premier numéro: Ceci est consdered mauvais style. Vos déclarations de type de données ne devraient pas avoir des contraintes. Laissez les contraintes aux fonctions, tout comme le paquet de conteneurs fait.

instance Eq (OutE vtype etype) where

Deuxième "question". Vous pouvez simplement ajouter deriving (Eq) après votre déclaration de données. Je devine que vous savez que et écrivez l'instance explicitement pour votre propre apprentissage (bon pour vous) ...

instance Eq (OutE vtype etype) where
    (==) = applyFunBy edgeValue (==)
    (/=) = applyFunBy edgeValue (/=)

Troisième numéro: vous ne pouvez pas comparer les valeurs d'équité si elles sont de la classe Eq. Donc, vous voulez dire etype est contrainte par l'équation:

instance (Eq etype) => Eq (OutE vtype etype) where
    (==) = applyFunBy edgeValue (==)
    (/=) = applyFunBy edgeValue (/=)

Quatrièmement, vous n'avez pas fait d'écrire une instance pour les deux (==) et (/ =). Les valeurs par défaut fonctionne une fois que vous définissez une.

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