Question

Cabbage.hs:

module Cabbage where 
class Cabbage a
  where foo :: a -> String      -- the parameter is only present for its type,
                                -- the parameter value will be ignored
        bar :: String -> a
quux :: Cabbage a => String -> a
quux s = bar (s ++ foo (undefined :: a))

Quand je compile (avec GHC) Je reçois ce message d'erreur:

Cabbage.hs:7:19:
    Ambiguous type variable `a' in the constraint:
      `Cabbage a' arising from a use of `foo' at Cabbage.hs:7:19-38
    Probable fix: add a type signature that fixes these type variable(s)

Je ne comprends pas pourquoi a est ambigu. Certes, le a dans la ligne 7 est la même que la a dans la ligne 6? Comment puis-je résoudre ce problème?

Sinon, est-il une meilleure façon de déclarer une constante par instance?

Était-ce utile?

La solution

Utilisation des variables de type scope vous pouvez laisser GHC savoir que le undefined :: a doit être le même (sinon a est juste un raccourci pour forall a. a).

: les variables de type scope doivent alors être explicitement forall qualifié
{-# LANGUAGE ScopedTypeVariables #-}
module Cabbage where 
class Cabbage a
  where foo :: a -> String      -- the parameter is only present for its type,
                                -- the parameter value will be ignored
        bar :: String -> a
quux :: forall a. Cabbage a => String -> a
quux s = bar (s ++ foo (undefined :: a))

Autres conseils

Le problème est que Haskell ne sait pas quelle instance de Cabbage qui correspond à foo là. Pour autant que je sache, il ne correspond pas au a en (undefined :: a) avec le a dans quux :: Cabbage a => String -> a

En supposant que ce que vous voulez, vous pouvez faire ceci:

quux :: Cabbage a => String -> a
quux s = result
    where result = bar (s ++ foo result)

Cela correspond foo et un bar ensemble afin qu'il utilise la même instance pour les deux, et que vous ne devez pas réellement la valeur de l'entrée pour foo, il touche le fond. Je ne sais pas d'une meilleure façon de faire des constantes par instance si. Espérons que quelqu'un d'autre viendra qui le fait.

vous pouvez extraire la partie polymorphes en fonction

quux :: Cabbage a => String -> a
quux s = quux' undefined
    where quux' :: Cabbage a => a -> a
          quux' x = bar (s ++ foo x)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top