I'm working with data structures that contain class methods from the
HList library (classes with functional dependencies). What I want to
be able to do is operate on high-level parts of the structure while
ignoring the type constraints of the lower-level components.
For example, say I have two data types and a class method:
> data Box x = Box x
> data Carton x = Carton x
> class Func x y | x -> y where func :: x -> y
I want to define a function 'isBoxed' that identifies whether a
function is in a Box or in a Carton that I can use like `isBoxed
(Carton func)`. Naively:
> class IsBoxed f b | f -> b where isBoxed :: f -> b
> instance IsBoxed (Box x) HTrue where isBoxed _ = hTrue
> instance IsBoxed (Carton x) HFalse where isBoxed _ = hFalse
(Where hTrue is a constructorish thing for the empty datatype HTrue.)
But `isBoxed (Box func)` fails in GHC with "Ambiguous type variables
`x', `y' in the constraint: `Func x y' arising from use of `func'...".
I realise that it's solvable if I have a finite number of instances
for Func, but what I actually want to box is functions with recursive
constraints like HList's hLookupByLabel.* I tried to borrow some ideas
(like TypeCast and empty data types) from the examples that come along
with HList (like keyword-arguments.hs) to no avail. Can anybody give
me a hand?
Thanks,
Jared Warren <warren at cs.queensu.ca>
* I could satisfy the type constraints with the infinite HList Record:
{Label hZero -> undefined, Label (hSucc hZero) -> undefined, ...}
...but that obviously runs into an infinite type.