
"Matthew Brecknell"
Bertram Felgenhauer:
How does
class F a where data B a :: * data E a :: * wrap :: B a -> E a unwrap :: E a -> B a
For any given call to "wrap" or "unwrap", how is the compiler supposed to determine which instance to use, given that "a" cannot be uniquely determined from the type of the function?
If it can't be uniquely determined then it blows up, as always. As far as my understanding of type classes goes, for any call to a function in a type class, the compiler must be able to determine a single instance to call. So if all we know is that we have a "B a" then all we can do is hope there's an instance "F a".
The same question also applies to Matthew's original formulation using functional dependencies:
class G a b | a -> b where data E a :: * wrap :: b -> E a unwrap :: E a -> b
Well here you certainly have less information, but you can still determine the instance - in both wrap and unwrap you have an "E a" which means the compiler will be able to work out some constraints on "a". There's also a "b" so it can also check that the fundep is respected, or incorporate the extra information into its decision making process. Note that both the above do type check and compile, and I have working instances of the latter: class CellBuilder c t n | c -> t n where data Cell c :: * makeCell :: t -> (MVar (Cell n)) -> Cell c unpackCell :: Cell c -> (t, (MVar (Cell n))) instance CellBuilder (Cons t n) t n where data Cell (Cons t n) = CellCons t (MVar (Cell n)) makeCell v mvar = CellCons v mvar unpackCell (CellCons v mvar) = (v, mvar) Matthew -- Matthew Sackman http://www.wellquite.org/