Converting MPTC+fundeps to type family / problem with polymorphic constant. Roles?

The "abstract-par" class has used multi-parameter type classes with fundeps: http://hackage.haskell.org/package/abstract-par-0.3.1/docs/Control-Monad-Par... 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) You can see the error when you try loading this file at this line: https://github.com/iu-parfunc/lvars/blob/b60cafb941ea8f2f333ada9b5206cd21211... "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*? Thanks, -Ryan

Oops, right after I sent I realized the answer ;-). I needed to delete one
character to uncurry the type function. That is:
"type Future m"
instead of
"type Future m a"
The fixed version is here:
https://github.com/iu-parfunc/lvars/blob/2b733d3044fde861e9c9b181258e7f9865a...
I'm still not totally sure what thought process and design guidelines I
should internalize for next time... perhaps: "make sure type families have
the minimum number of arguments that they need".
Best,
-Ryan
On Sun, Oct 6, 2013 at 8:27 PM, Ryan Newton
The "abstract-par" class has used multi-parameter type classes with fundeps:
http://hackage.haskell.org/package/abstract-par-0.3.1/docs/Control-Monad-Par...
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)
You can see the error when you try loading this file at this line:
https://github.com/iu-parfunc/lvars/blob/b60cafb941ea8f2f333ada9b5206cd21211...
"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*?
Thanks, -Ryan
participants (1)
-
Ryan Newton