[Haskell-cafe] Decoupling type classes (e.g. Applicative)?
Dominique Devriese
dominique.devriese at cs.kuleuven.be
Fri Oct 29 09:35:56 EDT 2010
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
More information about the Haskell-Cafe
mailing list