The Other Prelude
1 Call For Contribution
This fun project, called The Other Prelude, is a creative reconstruction of the standard Prelude. By disregarding history and compatibility, we get a clean sheet.
This project has no committee whatsoever. Issues are discussed on the talk page.
3 Naming Conventions
- Function names should be easy for beginners to consume.
- Specifically, The Other Prelude naming convention is to use
- descriptive symbols for functions that are naturally infix (e.g., is replaced bymplus)(++)
- whole English words and camelCase for functions (e.g., but notorElse)fmap
- descriptive symbols for functions that are naturally infix (e.g.,
4 The Hierarchy
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.
- - Minimalistic module.TheOtherPrelude
- - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.TheOtherPrelude.Utilities
5 Open Issues
- Should implyFunctoror the other way around?Monad
- When the same function has an infix and a prefix implementation, should one of them be outside the class to enforce consistency?
- Should Prelude functions use instead ofInteger?Int
- Should be a class rather than a type synonym?String
- The current proposal lacks a well thought mechanism. Should it be integrated intofail, or have a class of his own, or remain in theMonadZeroclass?Monad
What we have here right now is not ready to be adopted by existing projects. May be the class system extension proposal can make a difference.
7 The Code
Currently, the code is in Wiki form. If people do agree that the collaborative decisions begot something pretty, we'll have a group of files in darcs.haskell.org some time.
The imaginary Prelude as it stands,
module TheOtherPrelude where import Prelude (id, const) -- hide everything -- The idea is to rename 'fmap'. -- Both map :: (a -> b) -> [a] -> [b] (in ) -- and (.) :: (a -> b) -> (e -> a) -> (e -> b) (in (->) e) -- are good names, and are intuitively prefix and infix respectively. class Functor f where map :: (a -> b) -> f a -> f b (.) :: (Functor f) => (a -> b) -> f a -> f b (.) = map -- defined outside the class as an infix synonym for map. -- The following has been shamelessly copied from the -- Functor hierarchy proposal page (see links below). class (Functor p) => Applicative p where -- Minimal complete definition: return and (<*>). return :: a -> p a -- value lifting (<*>) :: p (a -> b) -> p a -> p b -- lifted application (>>) :: p a -> p b -> p b -- when the second is independent of the first -- Default definition: f >> g = (map (const id) f) <*> g apply :: (Applicative p) => p (a -> b) -> p a -> p b apply = (<*>) -- defined outside the class as a prefix synonym for (<*>). class (Applicative m) => Monad m where -- Minimal complete definition: one of join or (>>=). (>>=) :: m a -> (a -> m b) -> m b -- bind join :: m (m a) -> m a -- combining levels of structure -- Default definitions: x >>= f = join (map f x) join x = x >>= id -- We shamelessly copy from the MonadPlus reform proposal (link below) now. -- 'zero' will be used when pattern matching against refutable patterns in -- do-notation as well as to provide support for monad comprehensions. -- Should satisfy 'left zero': zero >>= f = zero class (Monad mz) => MonadZero mz where zero :: mz a -- Should satisfy 'monoid': -- zero ++ b = b; b ++ zero = b; (a ++ b) ++ c = a ++ (b ++ c) -- and 'left distribution': -- (a ++ b) >>= f = (a >>= f) ++ (b >>= f) class (MonadZero mp) => MonadPlus mp where (++) :: mp a -> mp a -> mp a -- Should satisfy 'monoid': -- zero `orElse` b = b; b `orElse` zero = b -- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c) -- and 'left catch': -- (return a) `orElse` b = a class (MonadZero mo) => MonadOr mo where orElse :: mo a -> mo a -> mo a
module TheOtherPrelude.Utilities where import Prelude () -- hide everything -- this is the if-then-else proposal -- the name has been chosen to reflect the magic of Church booleans! boolean True x _ = x boolean False _ y = y
8 How To Use
-- ''The Other Prelude'' is an alternative, not a replacement. -- So we need to hide everything from the Prelude import Prelude () -- This is just an example assuming there is nothing to hide import TheOtherPrelude -- Hopefully, this module will contain lift,... -- Standard convention is to use M.lift (instead of liftM) import qualified TheOtherPrelude.Monad.Kleisli as M
9 See also
- Class system extension proposal - Makes this proposal worth reading at last
- Functor hierarchy proposal - Making implyMonad m(adopted by The Other Prelude).Functor m
- If-then-else - Making a function (partially adopted by The Other Prelude, we are silent on the bigger issue of sugar).if
- MissingH - Functions "missing" from the Haskell Prelude/libraries.
- MonadPlus reform proposal - Clarifies ambiguities around MonadPlus laws (adopted by The Other Prelude)
- Mathematical prelude discussion - A numeric Prelude in good shape already. Will a merger be ever possible?
- Prelude extensions and Prelude function suggestions - Unlike The Other Prelude they enhance the Prelude.
- NotJustMaybe - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.