
I've been writing some code that relies heavily on the type system. Some of my polymorphic functions end up too polymorphic. I'm looking for some tips and references regarding prescribing poly-/mono-morphism. I know of three ways to do it: 1) rely on the monomorphism-restriction -- kind of scary in that its not explicitly obvious 2) introducing scoped-type variables of interest -- explicit and modular 3) introducing all type variables with a forall -- explicit but not modular The rest of this email is a discussion of a particular problem I'm having. Scoped-type variables worked in 6.4, but no longer in 6.6. I'm sure there's good reasons for this (I think I found a Peyton-Jones message regarding it in 6.4->6.5) I just didn't quite catch on to them. The problem is in the |bop| function: class SubType a v where -- the lack of fundeps is required by design inj :: a -> v lazyPrj :: v -> Maybe a bop :: forall x y z m c v . ( SubType x v, SubType y v, SubType z v , SubType (Fun m c v) v , Monad m, Comonad c ) => (x -> y -> z) -> Fun m c v bop op = Fun fn where fn = wrap fn' where fn' v0 = (inj . Fun) (wrap fn'') where fn'' v1 = inj (lazyPrj v0 `op` lazyPrj v1) wrap :: (v -> v) -> (c v -> m v) wrap = (return .) . (. counit) The explicit forall is needed to introduce the scoped type variables so that I can prescribe the type of |wrap|. After that, the monomorphism restriction on |wrap| takes care of the rest of my worries (that there is only one |m|, only one |c|, and only one |v|). If I leave the types to inference (i.e. drop the forall and the type ascription for |wrap|), then I end up with this type bop :: ( SubType x v2, SubType y v1, SubType z v1 , SubType (Fun m c v1) v2 , Monad m, Comonad c ) => (x -> y -> z) -> Fun m c v2 Note the multiple |v|s; they wreak havoc in the rest of my code. (The monomorphism restriction still takes care of the |m| and |c|.) I'd like to not have to introduce the forall, because with that comes introducing the entire context of the type. Thus I have to maintain any changes to the context, which I would prefer to leave to inference for modularity's sake. In 6.4 I was able to fix this without having to introduce the forall; I could introduce scoped type-variables in patterns to get the job done. That felt a bit like voodoo, especially when trying to get it right for 6.6--which I gave up on doing. I can post the code that works with 6.4 if anyone would like to see it (I just can't find it at the moment). I know there's some work on introducing partial signatures (fun pat | False = ...), but I don't see how to prescribe monomorphism for particular type variables in that way. Any thoughts on how to get the preferred signature using scoped-type variables in 6.6? I'd also welcome any references you might think are relevant. Thanks for your time, Nick