I have type classes, for all of which I would like to have some common behavior. My problem is explained in the following code:
class A a
class B b
class X x where
method :: (A a, B b) => x -> a -> b
data T = L | M | N
data U = P | Q | R
instance A T
instance B U
data Y = ZZZ
instance X Y where
method _ L = P
method _ M = Q
method _ N = R
When I load this module, I get the following error:
example.hs:19:14:
Could not deduce (a ~ T)
from the context (A a, B b)
bound by the type signature for method :: (A a, B b) => Y -> a -> b
at example.hs:(17,5)-(19,18)
`a' is a rigid type variable bound by
the type signature for method :: (A a, B b) => Y -> a -> b
at example.hs:17:5
In the pattern: N
In an equation for `method': method _ N = R
In the instance declaration for `X Y'
example.hs:19:18:
Could not deduce (b ~ U)
from the context (A a, B b)
bound by the type signature for method :: (A a, B b) => Y -> a -> b
at example.hs:(17,5)-(19,18)
`b' is a rigid type variable bound by
the type signature for method :: (A a, B b) => Y -> a -> b
at example.hs:17:5
In the expression: R
In an equation for `method': method _ N = R
In the instance declaration for `X Y'
Failed, modules loaded: none.
I am at loss what to do in this case. Even when T and U are instance of A and B, I get this error. If I cannot return a rigid type value from method, how do I code this part?
The signature
method :: (A a, B b) => x -> a -> bpromises thatmethodworks for every pair of types(a, b)withaan instance ofAandban instance ofB, but you define it to work only with two specific types.This is fundamentally different from interfaces in Java or the like, where the callee chooses which type is used, the only thing the caller knows is that interface X is implemented. In Haskell, given such a signature, the caller decides which types are used (here, what type is passed as second argument and what type shall be returned) and the callee has to be able to provide the demanded functionality (as long as the demanded types are instances of the required classes).
Without any methods in classes
AandBto analyse respectively construct values of an instance of that class, you cannot implementmethodother than withundefined(various degrees of undefinedness are possible due toseq), so you would have to tell the world that you are in fact usingTandU.Another way is to make
Xa multiparameter type class,However, that might require functional dependencies to resolve instances. Another way would be to use associated types,