
Hi all, I have a problem with the design of the Applicative type class, and I'm interested to know people's opinion about this. Currently, the Functor and Applicative type class are defined like this: class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b My problem is that in the grammar-combinators library [1], the pure combinator is too general for me. I would propose a hierarchy like the following: class Pointed f where pure :: a -> f a class ApplicativeC f where (<*>) :: f (a -> b) -> f a -> f b The original type class Applicative can then be recovered as follows, and the applicative laws can be specified informally in this class's definition. class (Pointed f, ApplicativeC f, Functor f) => Applicative f where This would allow me to restrict injected values to stuff I can lift into Template Haskell later on: class LiftablyPointed f where pureL :: (Lift a) -> a -> f a pureL' :: a -> Q Exp -> f a class (LiftablyPointed f, ApplicativeC) => LiftablyApplicative f where This problem currently makes it impossible for me to use the (<*>) combinator and I have to redefine it under a different name (I currently use (>>>)). To me the problem seems similar to the well known example of the inclusion of the fail primitive in the monad class, where the general opinion seems to be that it was a bad idea to include fail in the Monad class (see e.g. the article on the haskell wiki about handling failure [2]). I've been thinking about the following type class design principles: * Only include two functions in the same design class if both can be implemented in terms of each other. * Only introduce a dependency from type class A to type class B if all functions in type class B can be implemented in terms of the functions in type class A or if type class A is empty. (Disclaimer: I currently do not follow these principles myself ;)) I would like to know people's opinions about this. Are there any issues with this advice that I don't see? Have other people encountered similar problems? Any interesting references? Thanks, Dominique Footnotes: [1] http://projects.haskell.org/grammar-combinators/ [2] http://www.haskell.org/haskellwiki/Failure