Pourquoi ce type de variable ambiguë?
-
23-08-2019 - |
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?
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
).
{-# 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)