A general question about the use of classes in defining interfaces

Stimulated by remarks made during the discussion on the future of Haskell at the last Haskell Symposium, I have started to convert my new parsing library (constructed for the Lernet summerschool in Uruguay) into Cabalised form. In this library I have amongst others the class: class Applicative p where (<*>) :: p (b -> a) -> p b -> p a (<|>) :: p a -> p a -> p a (<$>) :: (b -> a) -> p b -> p a pReturn :: a -> p a pFail :: p a f <$> p = pReturn f <*> p which extends/deviates from the standard class Applicative, since I think these functions more or less belong together. I am happy to factor out <|> into a separate class. The problem which arises now is when I want to use the class Applicative as it is now defined in Control.Applicative. Functions like <$>, <$, <* and many have standard implementations in terms of the basic function pure and <*>. Although this looks fine at first sight, this is not so fine if we want to give more specialised (optimised, checking) implementations, as I am doing in my library. An example of this is e.g. in many, where I want to check that the parameter parser does not recognise the empty sequence since thi is non-sense, etc. Of course we can describe <* by p <* q = pure const <*> p <*> q but this is also rather inefficient; why first building a result if you are going to throw it away anyway? My life would be simpler if the extensions would either be incorporated in the class Applicative, with default definitions, and were not defined at top level, or in a class Extend_Applicative. More in general I think it is preferred to place common patterns in classes with a default implementation, so they can be redefined instead of defining them at top level. 1) Does everyone agree with this observation, and if not what am I missing? 2) Can we change the module Applicative to reflect my view? I think it can be done without implying heavy changes to other modules. Doaitse

Hi Doaitse, Ross, Doaitse wrote:
The problem which arises now is when I want to use the class Applicative as it is now defined in Control.Applicative. Functions like <$>, <$, <* and many have standard implementations in terms of the basic function pure and <*>. Although this looks fine at first sight, this is not so fine if we want to give more specialised (optimised, checking) implementations, as I am doing in my library.
There used to be the same problem with the Arrow class, with operators like &&& and *** having standard definitions, but not being redefineable due to not being class methods, which prevented (or at least made much more difficult) certain optimizations. After some prodding from me, Ross moved them into the Arrow class, with default definitions. I was and still am quite happy with that, and I'm not aware of any major drawbacks, except that it might not be so clear exactly where to draw the line between methods and top-level standard definitions if one opt to include more than the bare minimum of methods. Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham nhn@cs.nott.ac.uk This message has been checked for viruses but the contents of an attachment may still contain software viruses, which could damage your computer system: you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.
participants (2)
-
Henrik Nilsson
-
S. Doaitse Swierstra