
When I released the first version of container-classes (which I hacked on during AusHac), some people said I should split out the various folding, etc. into duplicates of the current Foldable class, etc. rather than having large monolithic classes. I've been working on this (see my more recent email with the subject along the lines of "fighting the type system"), and I think I've worked out how to do this: * Have one version of the class (when this makes sense) for values of kind * * Have another version that's closer to the original class for kind * -> * but allowing restrictions (e.g. allowing Set to be an instance of Functor). This is based upon Ganesh Sittampalam's rmonad package (http://hackage.haskell.org/package/rmonad). Rather than my original goal of forcing all kind * -> * values to be instances of the kind * classes, my new approach is to write instances that automatically make all instances of a * -> * class to also be an instance of the kind * class, and to use a newtype wrapper with a phantom type value to allow lifting/promotion of a kind * value to a kind * -> * value (e.g. "foo :: (Word8 -> Word8) -> ByteString -> ByteString; foo f = unpromote . fmap f . Promote" is a valid usage, rather than using the kind * function of rigidMap). My goal with this is that if I have duplicated a class Foo to allow restricted values, then it should be a drop-in replacement for the original in terms of _usage_ (i.e. the class and method/function names are the same, but the type signatures are not). However, I would appreciate the communities advice on a few matters: 1) How should I name the kind * versions? For example, the kind * version of Functor is currently called Mappable with a class method of rigidMap. What should I call the kind * version of Foldable and its corresponding methods? Is there a valid system I can use for these? 2) How far should I go? Should I restrict myself to the "data-oriented" classes such as Functor, Traversable, etc. or should I try to make restricted versions of Applicative and Monad? Assuming I should: 2a) Which namespace to use? Should Monad go in Data.Restricted.Monad to keep it in the same namespace as the other classes, or should I make it closer to base with Control.Restricted.Monad? 2b) Is it OK to promote functions that use a class to being class methods? When I was discussing this in #haskell several people mentioned that defining something like liftA2 for the Set instance of (restricted) Applicative would make more sense than the default <*> (since (a -> b) isnt' an instance of Ord). 2c) Should I keep the classes as-is, or should I explicitly put in the constraints mentioned in the Typeclassopedia (e.g. make Applicative an explicit superclass of Monad, and define return = pure for compatability reasons)? If so, should I bring over Pointed, etc. from category-extras to round out the set or just stick with classes that are already in base? 3) Am I wasting my time with this? -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com