And I'm trying to port it to use type families. But the following combination seems to be completely unusable for me right now:
class ParFuture m => ParIVar m where
new :: forall a . m (Future m a)
"Future" is a type-function from the superclass. I can't seem to use "new" in any way at any type without getting:
Control/Par/Class.hs:161:9:
Could not deduce (Future m a ~ Future m a0)
from the context (ParIVar m, FutContents m a)
bound by the type signature for
newFull_ :: (ParIVar m, FutContents m a) => a -> m (IVar m a)
at Control/Par/Class.hs:151:13-74
NB: `Future' is a type function, and may not be injective
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: m (IVar m a)
Actual type: m (Future m a0)
In the expression: (new :: m (IVar m a))
In a pattern binding: _ = (new :: m (IVar m a))
In an equation for `newFull_':
newFull_ a
= do { return undefined }
where
_ = (new :: m (IVar m a))
Failed, modules loaded: none.
Ok, so it seems like the type of "new" may just be intrinsically unusable. There is no way, by constraining the output of the "new" function for the type system to infer what input to the Future type function was. (Type function not reversable / injective.)
So am I just stuck? I don't want a dummy, unused argument just to communicate the type information to "new". Is this just a place where MPTC + fundeps works but type familes do not? Or is there some way that roles can save the day here? Do I need to say that the 'a' parameter has a representation role?