问题
I have this code:
{-# LANGUAGE MultiParamTypeClasses #-}
import System.Random (RandomGen(..))
class RandomGen gen => Shadow gen light where
shadowRay :: gen -> light -> Float
eval :: light -> Float
and I get that error:
[1 of 1] Compiling Main ( problem.hs, problem.o ) problem.hs:6:5: error: * Could not deduce (Shadow gen0 light) from the context: Shadow gen light bound by the type signature for: eval :: Shadow gen light => light -> float -> float at problem.hs:6:5-40 The type variable `gen0' is ambiguous * In the ambiguity check for `eval' To defer the ambiguity check to use sites, enable AllowAmbiguousTypes When checking the class method: eval :: forall gen light. Shadow gen light => forall float. light -> float -> float In the class declaration for `Shadow'
This is problem from GHC 7.10+. Before it was working. There is a fix if I add "gen" parameter to "eval", like:
eval :: gen -> light -> Float
But I don't want to add a new value parameter which will not be used. Is there some kind of other way for type resolution?
回答1:
The problem is that eval
does not use gen
, and so specialising its type is not enough to decide which gen
to use when picking the Shadow
instance to use. One possible solution is using a functional dependency to enforce that there will be only one gen
for each choice of light
:
{-# LANGUAGE FunctionalDependencies #-}
class RandomGen gen => Shadow gen light | light -> gen where
shadowRay :: gen -> light -> Float
eval :: light -> Float
It is possible, however, that you don't want or need to couple light
and gen
in this manner. In that case, you might want to consider the opposite alternative of removing gen
from the type class -- if gen
and light
aren't related, you don't need a multi-parameter type class to relate them:
class Shadow light where
shadowRay :: RandomGen gen => gen -> light -> Float
eval :: light -> Float
来源:https://stackoverflow.com/questions/41592832/could-not-deduce-error-on-multi-parameter-type-class