Minimal example code:
class IntegralAsType a where
value :: (Integral b) => a -> b
class (Num a, Fractional a, IntegralAsType q) => Zq q a | a -> q where
changeBase:: forall p b . (Zq q a, Zq p b) => a -> b
newtype (IntegralAsType q, Integral a) => ZqBasic q a = ZqBasic a deriving (Eq)
zqBasic :: forall q a . (IntegralAsType q, Integral a) => a -> ZqBasic q a
zqBasic x = ZqBasic (mod x (value (undefined::q)))
instance (IntegralAsType q, Integral a) => Zq q (ZqBasic q a) where
changeBase (ZqBasic x) = fromIntegral (value (undefined::p)) -- ZqBasic is an instance of Num
Here's a little background on what I'm trying to accomplish: IntegralAsType ensures type safety at compile time by preventing something like addition of two numbers with different modulus. ZqBasic is an internal representation of the Zq type, there are others, which is why Zq is defined the way it is. The goal is to get a system that is transparent to the internal representation.
My problem is with the changeBase function. I'm using explicit forall on the 'p' type, but I still get an "ambiguous type variable a0 in the constraint (IntegralAsType a0) arising from the use of value"
I'm confused on why I'm getting this error. In particular in a previous post, I got help with something like the "zqBasic" function, which appears to have the same setup as the changeBase function. I fixed the ambiguous variable error in zqBasic by adding the explicit quantifier 'forall q a .' Without this quantifier, I get an ambiguous type variable error. I understand why I need the quantifier there, but I don't understand why it doesn't seem to be helping for changeBase.
Thanks