https://wiki.haskell.org/api.php?action=feedcontributions&user=Nmessenger&feedformat=atomHaskellWiki - User contributions [en]2022-08-16T15:21:07ZUser contributionsMediaWiki 1.31.7https://wiki.haskell.org/index.php?title=Functor-Applicative-Monad_Proposal&diff=59702Functor-Applicative-Monad Proposal2015-04-29T16:03:27Z<p>Nmessenger: /* Proposal contents */ link to roles interaction</p>
<hr />
<div>Haskell calls a couple of historical accidents its own. While some of them, such as the "number classes" hierarchy, can be justified by pragmatism or lack of a strictly better suggestion, there is one thing that stood out as, well, not that: Applicative not being a superclass of Monad.<br />
<br />
The topic has been discussed multiple times in the past (cf. link section at the very end). '''This article describes the Haskell 2014 Applicative => Monad proposal (AMP)''', which was then implemented in GHC 7.10.<br />
<br />
Some relevant links:<br />
* [https://github.com/quchen/articles/blob/master/applicative_monad.md Initial text of the Haskell 2014 AMP]<br />
* [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/19482 AMP mailing list discussion]<br />
* Phase one: ticket [http://hackage.haskell.org/trac/ghc/ticket/8004 #8004]<br />
<br />
<br />
<br />
== Proposal contents ==<br />
<br />
The list of changes is as follows:<br />
<br />
# Applicative becomes a superclass of Monad, and is added to the Prelude.<br />
# Alternative becomes a superclass of MonadPlus (in addition to Monad, of course).<br />
# <s><hask>join</hask> is promoted into the Monad typeclass.</s> - Left out due to [https://ghc.haskell.org/trac/ghc/wiki/Roles2#join nontrivial breaking interaction] with [[Roles]]. Will "probably be fixed in the future", but for now it's off the table.<br />
<br />
The general rationale behind these changes:<br />
<br />
# ''Break as little code as possible.'' For example, do not move <hask>return</hask> to Applicative and remove <hask>pure</hask>. Instead, leave <hask>return</hask> in Monad, and give it <hask>pure</hask> as default implementation.<br />
# ''Change only things that are closely related to the proposal.'' For example, using <hask>join</hask> in a monad definition requires it to be a functor, so it goes hand in hand with the AMP. On the other hand, removing <hask>fail</hask> has nothing to do with what we're trying to accomplish.<br />
<br />
== Future-proofing current code ==<br />
<br />
GHC 7.8 will issue two types of warnings in order to encourage wide-scale code fixing. The following describes how to get rid of them, and as a result ensures your code builds both now and after the AMP is finished.<br />
<br />
=== Missing superclasses ===<br />
<br />
(Warnings of the type "Warning: X is an instance of C, but not D")<br />
<br />
* Add Applicative/Functor instances for all your Monads. You can simply derive these instances from the Monad by adding the following code:<br />
<haskell><br />
import Control.Applicative (Applicative(..))<br />
import Control.Monad (liftM, ap)<br />
<br />
-- Monad m<br />
<br />
instance Functor m where<br />
fmap = liftM<br />
<br />
instance Applicative m where<br />
pure = return<br />
(<*>) = ap<br />
</haskell><br />
<br />
* Add an Alternative instance for all instances of MonadPlus. This can again be done easily using<br />
<haskell><br />
import Control.Applicative (Alternative(..))<br />
import Control.Monad (mzero, mplus)<br />
<br />
-- MonadPlus m<br />
<br />
instance Alternative m where<br />
(<|>) = mplus<br />
empty = mzero<br />
</haskell><br />
<br />
=== Future Prelude names ===<br />
<br />
"The name X clashes with a future Prelude name" - Prelude will export functions called <hask><*></hask>, <hask>join</hask> and <hask>pure</hask>, so if a module defines its own versions of them, there will be name clashes. There are multiple ways of getting rid of this type of warning (in a future-proof way).<br />
<br />
# Change your code to not define functions named <hask><*></hask>, <hask>join</hask> or <hask>pure</hask>.<br />
# Import Prelude definitions you need explicitly. For example, <hask>import Prelude (map, (+))</hask> would not import <hask>join</hask>, so no warning is issued as the module is compatible with the Prelude exporting <hask>join</hask>. <hask>hiding</hask>.<br />
# Due to GHC internals, you cannot use <hask>hiding (join, (<*>), pure)</hask> to silence the warnings, although this method would be future-proof. If you want to use <hask>hiding</hask>, you will have to silence the warnings using a sledgehammer <code>-fno-warn-amp</code> compiler flag. (If you do so make sure you know what you're doing, otherwise your module ''will'' break in 7.10.) To make 7.10 not complain about the then unrecognized flag, it's best to specify it in a CPP block,<br />
<haskell><br />
{-# LANGUAGE CPP #-}<br />
#if __GLASGOW_HASKELL__ >= 707 && __GLASGOW_HASKELL__ < 710<br />
{-# OPTIONS_GHC -fno-warn-amp #-}<br />
#endif<br />
</haskell><br />
<br />
== Discussion and consequences ==<br />
<br />
<br />
=== It's the right thing to do™ ===<br />
<br />
Math. You've all heard this one, it's good and compelling so I don't need to spell it out.<br />
<br />
<br />
=== Redundant functions ===<br />
<br />
* <hask>pure</hask> and <hask>return</hask> do the same thing.<br />
* <hask>>></hask> and <hask>*></hask> are identical.<br />
* <hask>liftM</hask> and <hask>liftA</hask> are <hask>fmap</hask>. The <hask>liftM*</hask> are <hask>liftA*</hask>, <hask><*></hask> is <hask>ap</hask>.<br />
* Prelude's <hask>sequence</hask> requires <hask>Monad</hask> right now, while <hask>Applicative</hask> is sufficient to implement it. The more general version of this issue is captured by <hask>Data.Traversable</hask>, whose main typeclass implements the *same* functionality twice, namely <hask>traverse</hask> and <hask>mapM</hask>, and <hask>sequenceA</hask> and <hask>sequence</hask>.<br />
* The <hask>WrappedMonad</hask> type from <hask>Control.Applicative</hask> provides a semi-automatic way to using Functor/Applicative/Alternative functions for Monad/MonadPlus instances as a makeshift patch.<br />
<br />
That very much violates the "don't repeat yourself" principle, and even more so it ''forces'' the programmer to repeat himself to achieve maximal generality. It may be too late to take all redundancies out, but at least we can prevent new ones from being created.<br />
<br />
(Note that it is not proposed to remove any functions for compatibility reasons. Maybe some of them can be phased out in the long run, but that's beyond scope here.)<br />
<br />
<br />
=== Using Functor/Applicative functions in monadic code ===<br />
<br />
Whenever there's Monad code, you can use Functor/Applicative functions, without introducing an additional constraint. Keep in mind that "Functor/Applicative functions" does not only include what their typeclasses define but many more, for example <hask>void</hask>, <hask>(<$>)</hask>, <hask>(<**>)</hask>.<br />
<br />
Even if you think you have monadic code, strictly using the least restrictive functions may result in something that requires only Applicative. This is similar to writing a function that needs <hask>Int</hask>, but it turns out any <hask>Integral</hask> will do - more polymorphism for free.<br />
<br />
<br />
=== Compatibility issues ===<br />
<br />
These are the kinds of issues to be expected:<br />
<br />
# Monads lacking Functor or Applicative instances. This is easily fixable by either setting <hask>fmap = liftM</hask>, <hask>pure = return</hask> and <hask>(<*>) = ap</hask>, although more efficient implementations may exist, or by moving an already existing definition from <hask>Control.Applicative</hask> to the appropriate module.<br />
# This one is specific to building GHC: importing <hask>Control.Monad/Applicative</hask> introduces a circular module dependency. In this case, one can rely on handwritten implementations of the desired function, e.g. <hask>ap f x = f >>= ...</hask>.<br />
# Libraries using their own <hask>(<*>)</hask>. This one is potentially the most laborious consequence. For building GHC though, this only concerns Hoopl, and a handful of renames.<br />
<br />
<br />
<br />
=== Beginner friendliness ===<br />
<br />
How often did you say ...<br />
<br />
* "A Monad is always an Applicative but due to historical reasons it's not but you can easily verify it by setting <hask>pure = return</hask> and <hask>(<*>) = ap</hask>"<br />
* "<hask>liftM</hask> is <hask>fmap</hask> but not really." - "So when should I use <hask>fmap</hask> and when <hask>liftM</hask>?" - ''sigh''<br />
<br />
With the new hierarchy, the answer would ''always'' be "use the least restrictive one".<br />
<br />
== Applying the AMP to GHC and then Haskell in practice ==<br />
<br />
Proposed is a gradual introduction of the AMP in three phases:<br />
<br />
<br />
=== Prepare GHC ===<br />
<br />
Using a GHC fork with the full patch applied, find and fix all compilation errors introduced by the change by adding Functor/Applicative instances for all Monads.<br />
<br />
According to SPJ, adding an ad-hoc warning of sorts "Monad without Applicative detected" is not a problem, which will be crucial for the next phase. More specifically, issue a warning if:<br />
<br />
* Monad without Applicative<br />
* MonadPlus without Alternative<br />
* One of <hask><*></hask>, <hask>pure</hask>, <hask>join</hask> is defined in a different context to avoid naming conflicts, as these functions will go into the Prelude<br />
<br />
=== Prepare Hackage ===<br />
<br />
The warning just mentioned will hint to all authors that they should fix (or help others fix) the non-complying packages. This will ideally lead to libraries eventually adding Applicative instances, and changing their APIs if they redefine operators like <hask><*></hask>.<br />
<br />
After enough time has passed by so libraries adapted to the circumstances, move on to the next phase.<br />
<br />
<br />
=== Apply the proposal ===<br />
<br />
Once Hackage is prepared, applying the changes to the Base package is painless. However, this is not primarily a GHC, but a Haskell change. The previous steps were basically preparing the landscape, and when we've (hopefully) found out that it is a good idea to go through with it, it can be proposed to go into the Report. If we make it this far, the AMP should pass quite easily.<br />
<br />
<br />
<br />
== Previous proposals ==<br />
<br />
* Early 2011: [http://hackage.haskell.org/trac/ghc/ticket/4834 GHC ticket] &ndash; changes similar to this proposal, but closed as "not GHC, but Haskell". See [http://thread.gmane.org/gmane.comp.lang.haskell.libraries/14883/focus=14905 here] for the associated discussion.<br />
* [[The Other Prelude]]<br />
<br />
<br />
[[Category:Proposals]]<br />
[[Category:Functor]]<br />
[[Category:Applicative Functor]]<br />
[[Category:Monad]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=Talk:The_Other_Prelude&diff=11025Talk:The Other Prelude2007-02-04T18:29:37Z<p>Nmessenger: fmt</p>
<hr />
<div>i have no idea what i'm talking about here, but shouldn't "Monad m" imply "Functor m" if we're already starting with a clean slate? Also, what should the solution to "head", etc be? --[[User:JohannesAhlmann|Johannes Ahlmann]] 09:47, 21 December 2006 (UTC)<br />
<br />
:"Monad m" should imply "Functor m". By your question about "head", do you mean the problem of it being undefined on <hask>[]</hask>? [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
<br />
:: <hask>head</hask>, <hask>fst</hask> et cetera are projection functions. They can, in fact, be achieved by pattern matching, and are done that way often. It seems to me that at least the Prelude should be very mathematical and leave them out. YMMV. But <hask>Monad m</hask> should really imply <hask>Functor m</hask> if we want to be mathematical, and indeed we do. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
:: I'm not so sure whether you can just leave projections out of the prelude and it definitely wouldn't solve the underlying problem. Also I'd love to see some functions from MissingH (especially a sensible "split") in the prelude. Furthermore there's the question which functions from other libraries should be exported by Prelude (either, list functions, error/catch, fail, fmap, IO functions, mapM, maybe, read/reads, sequence, Numeric functions, ...). There definitely has to be some discussion about the necessity of including some of these. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:34, 23 December 2006 (UTC)<br />
<br />
== Naming ==<br />
<br />
Although the name of the page "The Other Prelude" does not seem to fit the Wiki standard (sentence case says: The other prelude), I left it as it appears to be a proper name when you read the content. [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
<br />
: Yes Brett, at least that was my intention. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
I propose the a rename to <hask>Prelude'</hask> for the module. Short, and parallels Haskell'. Also, I'm not fond of the name <hask>boolean</hask>. If there are no objections, I'll rename it to <hask>if'</hask> --[[User:Nmessenger|Nick Messenger]] 18:28, 4 February 2007 (UTC)<br />
<br />
== Issues ==<br />
<br />
I propose the following:<br />
<br />
* The Functor hierarchy proposal should be adopted.<br />
* There will be basic algebra modules in the Prelude hierarchy. Named, possibly, <hask>TheOtherPrelude.Algebra</hask>, if the numerical prelude people are happy with it. At this point I think the name, though clear, is very long. <br />
* I propose operators to be preferred over alphanumeric names. <hask>(++)</hask> seems way cooler than <hask>M.plus</hask>. YMMV. Vote here. About the precedence issue, I think proper usage of parentheses is enough for all practical purposes. Besides, (++) is associative.<br />
* <hask>join</hask> is the same as more specific <hask>concat</hask> as far as I get it. The task it accomplishes is more accurately described by the English word "join" than pseudoEnglish "concat". I think there should be no "concat" at all. One of the principle goals of this project is reducing the API.<br />
* This is basically a question... (>>=) is equivalent to <hask>concatMap</hask> in the list monad. I am not exactly a fan of the name, the Scala community uses <hask>flatMap</hask> as far as I recall. Should we include the function <hask>flatMap</hask> in the monad? Has one advantage, sometimes it's intuitive. I reckon it's intuitive whenever (=<<) is.<br />
--[[User:Uchchwhash|Pirated Dreams]] 12:38, 28 December 2006 (UTC)<br />
<br />
:: If we really want to go for consistency, then perhaps 'joinMap'? --[[User:Nmessenger|Nmessenger]] 00:05, 4 January 2007 (UTC)<br />
<br />
::: <hask>joinMap</hask> is consistent in that is says what it does :) <hask>flatMap</hask> would have introduced it (<hask>join . map</hask>) as a bit more sophisticated ''concept'' (highlighting the map underneath the monadic container). Doesn't really matter. Thanks for pulling <hask>(>>)</hask> up. I am not aware of any caveats, though the experts may jump in and say "you see, this and that are the reasons we didn't do it ..." and ruin the day ;) --[[User:Uchchwhash|Pirated Dreams]] 11:02, 4 January 2007 (UTC)<br />
<br />
== Duplicate definitions ==<br />
<br />
I found out that we have been duplicating Gofer's prelude here :p<br />
<br />
Also, projecting the future, I see we'll be seeing duplicate definitions in the prelude (like <hask>map</hask> and <hask>(.)</hask>). I think we can do something here. Mostly, this renaming is worthwhile for one reason: sometimes they are useful as operators, sometimes as functions. I think we should keep one of them inside the class, the other outside. This guarantees that they mean exactly the same thing. This provides cleaner documentation and consistency. If someone wants to provide an alternative defintion of <hask>(.)</hask> (say) s/he can hide it from the prelude. --[[User:Uchchwhash|Pirated Dreams]] 11:11, 4 January 2007 (UTC)<br />
<br />
: should <hask><*></hask> be named <hask>*>></hask>? the current is symmetric-looking but the meaning is not. --[[User:Uchchwhash|Pirated Dreams]] 20:37, 22 January 2007 (UTC)<br />
<br />
:: The <hask>Applicative</hask> class in the <hask>Control.Applicative</hask> module names this function <hask>(*>)</hask>. I'm not sure if this is better than its name in <hask>Monad</hask> or not. My current inclination is <hask>(>>)</hask> for backwards compatibility, but that's not so important in this exercise. Re: duplicate names; I've thought about this a little, and the same argument could be applied to any class that defines methods in terms of each other. <hask>(<)</hask>, <hask>(<=)</hask>, <hask>(>)</hask>, and <hask>(>=)</hask> could be lifted from <hask>Ord</hask> (and defined in terms of <hask>compare</hask>), <hask>(>>)</hask>/<hask>(*>)</hask> from <hask>Applicative</hask>, <hask>join</hask> from <hask>Monad</hask>, etc. I'm not sure where to draw the line, so I'd defer it. --[[User:Nmessenger|Nick Messenger]] 16:45, 3 February 2007 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=Talk:The_Other_Prelude&diff=11024Talk:The Other Prelude2007-02-04T18:28:10Z<p>Nmessenger: fmt, Prelude', and boolean</p>
<hr />
<div>i have no idea what i'm talking about here, but shouldn't "Monad m" imply "Functor m" if we're already starting with a clean slate? Also, what should the solution to "head", etc be? --[[User:JohannesAhlmann|Johannes Ahlmann]] 09:47, 21 December 2006 (UTC)<br />
<br />
:"Monad m" should imply "Functor m". By your question about "head", do you mean the problem of it being undefined on <hask>[]</hask>? [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
<br />
:: <hask>head</hask>, <hask>fst</hask> et cetera are projection functions. They can, in fact, be achieved by pattern matching, and are done that way often. It seems to me that at least the Prelude should be very mathematical and leave them out. YMMV. But <hask>Monad m</hask> should really imply <hask>Functor m</hask> if we want to be mathematical, and indeed we do. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
:: I'm not so sure whether you can just leave projections out of the prelude and it definitely wouldn't solve the underlying problem. Also I'd love to see some functions from MissingH (especially a sensible "split") in the prelude. Furthermore there's the question which functions from other libraries should be exported by Prelude (either, list functions, error/catch, fail, fmap, IO functions, mapM, maybe, read/reads, sequence, Numeric functions, ...). There definitely has to be some discussion about the necessity of including some of these. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:34, 23 December 2006 (UTC)<br />
<br />
== Naming ==<br />
<br />
Although the name of the page "The Other Prelude" does not seem to fit the Wiki standard (sentence case says: The other prelude), I left it as it appears to be a proper name when you read the content. [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
<br />
: Yes Brett, at least that was my intention. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
I propose the a rename to <hask>Prelude'</hask> for the module. Short, and parallels Haskell'. Also, I'm not fond of the name <hask>boolean</hask>. If there are no objections, I'll rename it to <hask>if'</hask> --[[User:Nmessenger|Nick Messenger]] 18:28, 4 February 2007 (UTC)<br />
<br />
== Issues ==<br />
<br />
I propose the following:<br />
<br />
* The Functor hierarchy proposal should be adopted.<br />
* There will be basic algebra modules in the Prelude hierarchy. Named, possibly, <hask>TheOtherPrelude.Algebra</hask>, if the numerical prelude people are happy with it. At this point I think the name, though clear, is very long. <br />
* I propose operators to be preferred over alphanumeric names. <hask>(++)</hask> seems way cooler than <hask>M.plus</hask>. YMMV. Vote here. About the precedence issue, I think proper usage of parentheses is enough for all practical purposes. Besides, (++) is associative.<br />
* <hask>join</hask> is the same as more specific <hask>concat</hask> as far as I get it. The task it accomplishes is more accurately described by the English word "join" than pseudoEnglish "concat". I think there should be no "concat" at all. One of the principle goals of this project is reducing the API.<br />
* This is basically a question... (>>=) is equivalent to <hask>concatMap</hask> in the list monad. I am not exactly a fan of the name, the Scala community uses <hask>flatMap</hask> as far as I recall. Should we include the function <hask>flatMap</hask> in the monad? Has one advantage, sometimes it's intuitive. I reckon it's intuitive whenever (=<<) is.<br />
--[[User:Uchchwhash|Pirated Dreams]] 12:38, 28 December 2006 (UTC)<br />
<br />
:: If we really want to go for consistency, then perhaps 'joinMap'? --[[User:Nmessenger|Nmessenger]] 00:05, 4 January 2007 (UTC)<br />
<br />
::: <hask>joinMap</hask> is consistent in that is says what it does :) <hask>flatMap</hask> would have introduced it (<hask>join . map</hask>) as a bit more sophisticated ''concept'' (highlighting the map underneath the monadic container). Doesn't really matter. Thanks for pulling <hask>(>>)</hask> up. I am not aware of any caveats, though the experts may jump in and say "you see, this and that are the reasons we didn't do it ..." and ruin the day ;)<br />
--[[User:Uchchwhash|Pirated Dreams]] 11:02, 4 January 2007 (UTC)<br />
<br />
== Duplicate definitions ==<br />
<br />
I found out that we have been duplicating Gofer's prelude here :p<br />
<br />
Also, projecting the future, I see we'll be seeing duplicate definitions in the prelude (like <hask>map</hask> and <hask>(.)</hask>). I think we can do something here. Mostly, this renaming is worthwhile for one reason: sometimes they are useful as operators, sometimes as functions. I think we should keep one of them inside the class, the other outside. This guarantees that they mean exactly the same thing. This provides cleaner documentation and consistency. If someone wants to provide an alternative defintion of <hask>(.)</hask> (say) s/he can hide it from the prelude. --[[User:Uchchwhash|Pirated Dreams]] 11:11, 4 January 2007 (UTC)<br />
<br />
: should <hask><*></hask> be named <hask>*>></hask>? the current is symmetric-looking but the meaning is not. --[[User:Uchchwhash|Pirated Dreams]] 20:37, 22 January 2007 (UTC)<br />
<br />
:: The <hask>Applicative</hask> class in the <hask>Control.Applicative</hask> module names this function <hask>(*>)</hask>. I'm not sure if this is better than its name in <hask>Monad</hask> or not. My current inclination is <hask>(>>)</hask> for backwards compatibility, but that's not so important in this exercise. Re: duplicate names; I've thought about this a little, and the same argument could be applied to any class that defines methods in terms of each other. <hask>(<)</hask>, <hask>(<=)</hask>, <hask>(>)</hask>, and <hask>(>=)</hask> could be lifted from <hask>Ord</hask> (and defined in terms of <hask>compare</hask>), <hask>(>>)</hask>/<hask>(*>)</hask> from <hask>Applicative</hask>, <hask>join</hask> from <hask>Monad</hask>, etc. I'm not sure where to draw the line, so I'd defer it. --[[User:Nmessenger|Nick Messenger]] 16:45, 3 February 2007 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=If-then-else&diff=11020If-then-else2007-02-04T07:05:06Z<p>Nmessenger: (?:) -> (?), much better</p>
<hr />
<div>== Replace syntactic sugar by a function ==<br />
<br />
For processing conditions,<br />
the <hask>if-then-else</hask> syntax was defined in Haskell98.<br />
However it could be simply replaced by the function <hask>if'</hask><br />
with<br />
<haskell><br />
if' :: Bool -> a -> a -> a<br />
if' True x _ = x<br />
if' False _ y = y<br />
</haskell><br />
Unfortunately there is no such function in the Prelude.<br />
<br />
== Advocacy ==<br />
<br />
=== Advantages ===<br />
<br />
The advantages of the function <hask>if'</hask><br />
over the syntax <hask>if-then-else</hask><br />
are the same like for all such alternatives.<br />
So let me repeat two important non-syntactic strengths of Haskell:<br />
<br />
* types: classification, documentation<br />
* higher order functions: combinators<br />
<br />
If <hask>if'</hask> would be a regular function,<br />
each language tool can process it without hassle.<br />
Haddock can generate documentation for it,<br />
a text editor can make suggestions for values to insert,<br />
Hoogle can retrieve that function.<br />
<br />
For example, the Hoogle query<br />
<haskell><br />
[Bool] -> [a] -> [a] -> [a]<br />
</haskell><br />
may return<br />
<haskell><br />
zipWith3 if'<br />
</haskell><br />
<br />
<br />
=== Use cases ===<br />
<br />
Each of the following functions could be defined in terms of <hask>if'</hask>.<br />
Actually, they do not even need to be in Prelude<br />
because they can be constructed so easily.<br />
<br />
That function is harder to explain in English,<br />
than by its implementation. :-)<br />
<haskell><br />
zipIf :: [Bool] -> [a] -> [a] -> [a]<br />
zipIf = zipWith3 if'<br />
</haskell><br />
<br />
Infix version. This duplicates the ternary operator of C-like languages, and can be used: <hask>(cond ? exp1 $ exp2)</hask>. Additionally, Church booleans can be represented compactly by sectioning on (?), i.e. <hask>(True?) = const; (False?) = flip const</hask><br />
<haskell><br />
infixr 1 ?<br />
(?) :: Bool -> a -> a -> a<br />
(?) = if'<br />
</haskell><br />
<br />
From a list of expressions choose the one,<br />
whose condition is true.<br />
The first parameter is the default value.<br />
It is returned if no condition applies.<br />
<haskell><br />
select :: a -> [(Bool, a)] -> a<br />
select = foldr (uncurry if')<br />
</haskell><br />
See [[Case]].<br />
<br />
Easy lifting into monads (MonadReader in this case)<br />
<haskell><br />
ifF :: (a -> Bool) -> (a -> b) -> (a -> b) -> (a -> b)<br />
ifF = liftM3 if'<br />
</haskell><br />
<br />
<br />
=== Why add this function to Prelude? ===<br />
<br />
Actually people could define <hask>if'</hask> in each module,<br />
where they need it,<br />
or import it from a <hask>Utility</hask> module,<br />
that must be provided in each project.<br />
Both solutions are tedious and<br />
contradict to modularization and software re-usage.<br />
The central question is, whether <hask>if'</hask> is an idiom,<br />
that is so general that it should be in the Prelude, or not.<br />
I think it is, otherwise it wouldn't have get a special syntax.<br />
<br />
=== If-Then-Else vs. guards ===<br />
<br />
Some people (any exact statistics?) prefer guards to <hask>if-then-else</hask>.<br />
This practice has its own drawbacks,<br />
see [[Syntactic sugar/Cons]] and [[Things to avoid]].<br />
<br />
<!--<br />
The default case is always built-in<br />
and needs no extra compiler check.<br />
Compare<br />
<haskell><br />
flipCond cond (x,y) | cond = (x,y)<br />
| otherwise = (y,x)<br />
</haskell><br />
<haskell><br />
flipCond cond (x,y) = if' cond (x,y) (y,x)<br />
</haskell><br />
--><br />
<br />
=== Is If-Then-Else so important? ===<br />
<br />
Counting <hask>if-then-else</hask> or <hask>if'</hask><br />
in today's Haskell programs<br />
isn't a good measure for the importance a <hask>if'</hask> function,<br />
because<br />
* frequently guards are used instead of <hask>if-then-else</hask><br />
* there is no standard function, and this let people stick to work-arounds.<br />
<br />
=== What is so bad about the if-then-else sugar? ===<br />
<br />
Since syntactic sugar introduces its own syntactic rules,<br />
it is hard to predict how it interferes with other syntactic constructs.<br />
This special syntax for instance led to conflicts with do notation.<br />
A [http://hackage.haskell.org/trac/haskell-prime/wiki/DoAndIfThenElse syntactic extension] to solve this problem is proposed for Haskell'.<br />
It is not known what conflicts this extension might cause in future.<br />
<br />
<br />
=== Why breaking lots of old and unmaintained code? ===<br />
<br />
Haskell without <hask>if-then-else</hask> syntax<br />
makes Haskell more logical and consistent.<br />
There is no longer confusion to beginners like:<br />
"What is so special about if-then-else, that it needs a separate syntax?<br />
I though it could be simply replaced by a function.<br />
Maybe there is some subtlety that I'm not able to see right now."<br />
There is no longer confusion with the interference of<br />
<hask>if-then-else</hask> syntax with <hask>do</hask> notation.<br />
Removing <hask>if-then-else</hask> simplifies every language tool,<br />
say compiler, text editor, analyzer and so on.<br />
<br />
If we arrive at [[Haskell two]] some day, (http://haskell.org/hawiki/HaskellTwo)<br />
it will certainly be incompatible to former Haskell versions.<br />
This does not mean, that old code must be thrown away.<br />
There should be one tool,<br />
that converts Haskell 98 and Haskell' to Haskell-2.<br />
Having '''one''' tool for this purpose<br />
is better than blowing '''all''' language tools with legacy code.<br />
Syntactic replacements like <hask>if-then-else</hask> syntax to<br />
<hask>if'</hask> function should be especially simple.<br />
<br />
<br />
=== Summary ===<br />
<br />
* Light proposal, compatible with Haskell 98: Add <hask>if'</hask> to the Prelude, maybe with a different name.<br />
* Full proposal, incompatible with Haskell 98 and Haskell': Additionally remove <hask>if-then-else</hask> syntax<br />
<br />
<br />
=== See also ===<br />
<br />
* [[Syntactic sugar/Cons]]<br />
* [[Things to avoid/Discussion]]<br />
<br />
<br />
== Objections ==<br />
<br />
Haskell is not intended to be a minimalistic language,<br />
but to be one that is easy to read.<br />
<hask>if-then-else</hask> resembles a phrase from English language.<br />
It shows clearly which expression is returned on a fulfilled condition,<br />
and which one is returned for an unsatisfied condition.<br />
It is thus easier to read.<br />
The special syntax saves parentheses around its arguments.<br />
If properly indented, like<br />
<haskell><br />
if a<br />
then b<br />
else c<br />
</haskell><br />
or<br />
<haskell><br />
if a<br />
then b else c<br />
</haskell><br />
then there is no conflict with the <hask>do</hask>-notation.<br />
<br />
[[Category:Proposals]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=10985The Other Prelude2007-02-03T17:00:44Z<p>Nmessenger: comment fmt, added Class Heirarchy Proposal (commented-out since invalid)</p>
<hr />
<div>== Call For Contribution ==<br />
<br />
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.<br />
<br />
== Committee ==<br />
<br />
This project has no committee whatsoever. Issues are discussed on [[Talk:The Other Prelude|the talk page]].<br />
<br />
== Naming Conventions ==<br />
<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
<br />
* When the same function has an infix and a prefix implementation, should one of them be outside the class to enforce consistency?<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>? Maybe <hask>Integral n => n</hask> or <hask>Ix i => i</hask> in some cases?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
* The current proposal lacks a well thought <hask>fail</hask> mechanism. Should it be integrated into <hask>MonadZero</hask>, or have a class of his own, or remain in the <hask>Monad</hask> class?<br />
<br />
== Reality ==<br />
<br />
What we have here right now is not ready to be adopted by existing projects. The [[class system extension proposal]] might make a difference.<br />
<br />
== The Code ==<br />
<br />
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.<br />
<br />
The imaginary Prelude as it stands:<br />
<br />
=== <hask>TheOtherPrelude.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude where<br />
<br />
import Prelude (id, const, flip) -- hide almost everything<br />
<br />
-- The idea is to rename 'fmap'.<br />
-- Both map :: (a -> b) -> [a] -> [b] (in [])<br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) (in (->) e)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
-- 'map' is aliased as (.) below.<br />
<br />
class Functor f where<br />
map :: (a -> b) -> f a -> f b<br />
<br />
(.) :: (Functor f) => (a -> b) -> f a -> f b<br />
(.) = map<br />
<br />
class (Functor p) => Applicative p where<br />
-- Minimal complete definition: return and (<*>).<br />
return :: a -> p a -- value lifting<br />
(<*>) :: p (a -> b) -> p a -> p b -- lifted application<br />
(>>) :: p a -> p b -> p b -- when the second is independent of the first<br />
<br />
pa >> pb = map (const id) pa <*> pb<br />
--map f pa = return f <*> pa -- see Class system extension proposal, below<br />
<br />
apply :: (Applicative p) => p (a -> b) -> p a -> p b<br />
apply = (<*>)<br />
<br />
class (Applicative m) => Monad m where<br />
-- Minimal complete definition: one of join or (>>=).<br />
(>>=) :: m a -> (a -> m b) -> m b -- bind<br />
join :: m (m a) -> m a -- combining levels of structure<br />
<br />
ma >>= k = join (map k ma)<br />
join mma = mma >>= id<br />
--mf <*> ma = mf >>= flip map ma -- see Class system extension proposal, below<br />
--ma >> mb = ma >>= const mb<br />
--map f ma = ma >>= return . f -- this depends on (.), which is map! Be careful.<br />
<br />
-- We copy from the MonadPlus reform proposal (link below) now.<br />
-- 'zero' will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
<br />
class (Monad mz) => MonadZero mz where<br />
-- Should satisfy 'left zero': zero >>= f = zero<br />
zero :: mz a<br />
<br />
class (MonadZero mp) => MonadPlus mp where<br />
-- Should satisfy 'monoid':<br />
-- zero ++ b = b; b ++ zero = b<br />
-- (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution':<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
(++) :: mp a -> mp a -> mp a<br />
<br />
class (MonadZero mo) => MonadOr mo where<br />
-- Should satisfy 'monoid':<br />
-- zero `orElse` b = b; b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch':<br />
-- (return a) `orElse` b = a<br />
orElse :: mo a -> mo a -> mo a<br />
</haskell><br />
<br />
=== <hask>TheOtherPrelude/Utilities.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude.Utilities where<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
</haskell><br />
<br />
== How To Use ==<br />
<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude ()<br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude<br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M<br />
</haskell><br />
<br />
== See also ==<br />
<br />
* [[Class system extension proposal]] - Makes this proposal worth reading at last<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [http://haskell.org/hawiki/NotJustMaybe NotJustMaybe] - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.<br />
<br />
[[Category:Proposals]]<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=Talk:The_Other_Prelude&diff=10983Talk:The Other Prelude2007-02-03T16:47:04Z<p>Nmessenger: lean towards (>>)</p>
<hr />
<div>i have no idea what i'm talking about here, but shouldn't "Monad m" imply "Functor m" if we're already starting with a clean slate? Also, what should the solution to "head", etc be? --[[User:JohannesAhlmann|Johannes Ahlmann]] 09:47, 21 December 2006 (UTC)<br />
:"Monad m" should imply "Functor m". By your question about "head", do you mean the problem of it being undefined on <hask>[]</hask>? [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
:: <hask>head</hask>, <hask>fst</hask> et cetera are projection functions. They can, in fact, be achieved by pattern matching, and are done that way often. It seems to me that at least the Prelude should be very mathematical and leave them out. YMMV. But <hask>Monad m</hask> should really imply <hask>Functor m</hask> if we want to be mathematical, and indeed we do. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
:: I'm not so sure whether you can just leave projections out of the prelude and it definitely wouldn't solve the underlying problem. Also I'd love to see some functions from MissingH (especially a sensible "split") in the prelude. Furthermore there's the question which functions from other libraries should be exported by Prelude (either, list functions, error/catch, fail, fmap, IO functions, mapM, maybe, read/reads, sequence, Numeric functions, ...). There definitely has to be some discussion about the necessity of including some of these. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:34, 23 December 2006 (UTC)<br />
<br />
==Naming==<br />
Although the name of the page "The Other Prelude" does not seem to fit the Wiki standard (sentence case says: The other prelude), I left it as it appears to be a proper name when you read the content. [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
: Yes Brett, at least that was my intention. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
== Issues ==<br />
I propose the following:<br />
* The Functor hierarchy proposal should be adopted.<br />
* There will be basic algebra modules in the Prelude hierarchy. Named, possibly, <hask>TheOtherPrelude.Algebra</hask>, if the numerical prelude people are happy with it. At this point I think the name, though clear, is very long. <br />
* I propose operators to be preferred over alphanumeric names. <hask>(++)</hask> seems way cooler than <hask>M.plus</hask>. YMMV. Vote here. About the precedence issue, I think proper usage of parentheses is enough for all practical purposes. Besides, (++) is associative.<br />
* <hask>join</hask> is the same as more specific <hask>concat</hask> as far as I get it. The task it accomplishes is more accurately described by the English word "join" than pseudoEnglish "concat". I think there should be no "concat" at all. One of the principle goals of this project is reducing the API.<br />
* This is basically a question... (>>=) is equivalent to <hask>concatMap</hask> in the list monad. I am not exactly a fan of the name, the Scala community uses <hask>flatMap</hask> as far as I recall. Should we include the function <hask>flatMap</hask> in the monad? Has one advantage, sometimes it's intuitive. I reckon it's intuitive whenever (=<<) is.<br />
--[[User:Uchchwhash|Pirated Dreams]] 12:38, 28 December 2006 (UTC)<br />
** If we really want to go for consistency, then perhaps 'joinMap'? [[User:Nmessenger|Nmessenger]] 00:05, 4 January 2007 (UTC)<br />
::: <hask>joinMap</hask> is consistent in that is says what it does :) <hask>flatMap</hask> would have introduced it (<hask>join . map</hask>) as a bit more sophisticated ''concept'' (highlighting the map underneath the monadic container). Doesn't really matter. Thanks for pulling <hask>(>>)</hask> up. I am not aware of any caveats, though the experts may jump in and say "you see, this and that are the reasons we didn't do it ..." and ruin the day ;)<br />
--[[User:Uchchwhash|Pirated Dreams]] 11:02, 4 January 2007 (UTC)<br />
<br />
== Duplicate definitions ==<br />
I found out that we have been duplicating Gofer's prelude here :p<br />
<br />
Also, projecting the future, I see we'll be seeing duplicate definitions in the prelude (like <hask>map</hask> and <hask>(.)</hask>). I think we can do something here. Mostly, this renaming is worthwhile for one reason: sometimes they are useful as operators, sometimes as functions. I think we should keep one of them inside the class, the other outside. This guarantees that they mean exactly the same thing. This provides cleaner documentation and consistency. If someone wants to provide an alternative defintion of <hask>(.)</hask> (say) s/he can hide it from the prelude.<br />
--[[User:Uchchwhash|Pirated Dreams]] 11:11, 4 January 2007 (UTC)<br />
: should <hask><*></hask> be named <hask>*>></hask>? the current is symmetric-looking but the meaning is not. --[[User:Uchchwhash|Pirated Dreams]] 20:37, 22 January 2007 (UTC)<br />
:: The <hask>Applicative</hask> class in the <hask>Control.Applicative</hask> module names this function <hask>(*>)</hask>. I'm not sure if this is better than its name in <hask>Monad</hask> or not. My current inclination is (>>) for backwards compatibility, but that's not so important in this exercise. Re: duplicate names; I've thought about this a little, and the same argument could be applied to any class that defines methods in terms of each other. <hask>(<)</hask>, <hask>(<=)</hask>, <hask>(>)</hask>, and <hask>(>=)</hask> could be lifted from <hask>Ord</hask> (and defined in terms of <hask>compare</hask>), <hask>(>>)</hask>/<hask>(*>)</hask> from <hask>Applicative</hask>, <hask>join</hask> from <hask>Monad</hask>, etc. I'm not sure where to draw the line, so I'd defer it. [[User:Nmessenger|Nick Messenger]] 16:45, 3 February 2007 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=Talk:The_Other_Prelude&diff=10982Talk:The Other Prelude2007-02-03T16:45:09Z<p>Nmessenger: names, re: (>>) and duplicates</p>
<hr />
<div>i have no idea what i'm talking about here, but shouldn't "Monad m" imply "Functor m" if we're already starting with a clean slate? Also, what should the solution to "head", etc be? --[[User:JohannesAhlmann|Johannes Ahlmann]] 09:47, 21 December 2006 (UTC)<br />
:"Monad m" should imply "Functor m". By your question about "head", do you mean the problem of it being undefined on <hask>[]</hask>? [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
:: <hask>head</hask>, <hask>fst</hask> et cetera are projection functions. They can, in fact, be achieved by pattern matching, and are done that way often. It seems to me that at least the Prelude should be very mathematical and leave them out. YMMV. But <hask>Monad m</hask> should really imply <hask>Functor m</hask> if we want to be mathematical, and indeed we do. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
:: I'm not so sure whether you can just leave projections out of the prelude and it definitely wouldn't solve the underlying problem. Also I'd love to see some functions from MissingH (especially a sensible "split") in the prelude. Furthermore there's the question which functions from other libraries should be exported by Prelude (either, list functions, error/catch, fail, fmap, IO functions, mapM, maybe, read/reads, sequence, Numeric functions, ...). There definitely has to be some discussion about the necessity of including some of these. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:34, 23 December 2006 (UTC)<br />
<br />
==Naming==<br />
Although the name of the page "The Other Prelude" does not seem to fit the Wiki standard (sentence case says: The other prelude), I left it as it appears to be a proper name when you read the content. [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
: Yes Brett, at least that was my intention. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
== Issues ==<br />
I propose the following:<br />
* The Functor hierarchy proposal should be adopted.<br />
* There will be basic algebra modules in the Prelude hierarchy. Named, possibly, <hask>TheOtherPrelude.Algebra</hask>, if the numerical prelude people are happy with it. At this point I think the name, though clear, is very long. <br />
* I propose operators to be preferred over alphanumeric names. <hask>(++)</hask> seems way cooler than <hask>M.plus</hask>. YMMV. Vote here. About the precedence issue, I think proper usage of parentheses is enough for all practical purposes. Besides, (++) is associative.<br />
* <hask>join</hask> is the same as more specific <hask>concat</hask> as far as I get it. The task it accomplishes is more accurately described by the English word "join" than pseudoEnglish "concat". I think there should be no "concat" at all. One of the principle goals of this project is reducing the API.<br />
* This is basically a question... (>>=) is equivalent to <hask>concatMap</hask> in the list monad. I am not exactly a fan of the name, the Scala community uses <hask>flatMap</hask> as far as I recall. Should we include the function <hask>flatMap</hask> in the monad? Has one advantage, sometimes it's intuitive. I reckon it's intuitive whenever (=<<) is.<br />
--[[User:Uchchwhash|Pirated Dreams]] 12:38, 28 December 2006 (UTC)<br />
** If we really want to go for consistency, then perhaps 'joinMap'? [[User:Nmessenger|Nmessenger]] 00:05, 4 January 2007 (UTC)<br />
::: <hask>joinMap</hask> is consistent in that is says what it does :) <hask>flatMap</hask> would have introduced it (<hask>join . map</hask>) as a bit more sophisticated ''concept'' (highlighting the map underneath the monadic container). Doesn't really matter. Thanks for pulling <hask>(>>)</hask> up. I am not aware of any caveats, though the experts may jump in and say "you see, this and that are the reasons we didn't do it ..." and ruin the day ;)<br />
--[[User:Uchchwhash|Pirated Dreams]] 11:02, 4 January 2007 (UTC)<br />
<br />
== Duplicate definitions ==<br />
I found out that we have been duplicating Gofer's prelude here :p<br />
<br />
Also, projecting the future, I see we'll be seeing duplicate definitions in the prelude (like <hask>map</hask> and <hask>(.)</hask>). I think we can do something here. Mostly, this renaming is worthwhile for one reason: sometimes they are useful as operators, sometimes as functions. I think we should keep one of them inside the class, the other outside. This guarantees that they mean exactly the same thing. This provides cleaner documentation and consistency. If someone wants to provide an alternative defintion of <hask>(.)</hask> (say) s/he can hide it from the prelude.<br />
--[[User:Uchchwhash|Pirated Dreams]] 11:11, 4 January 2007 (UTC)<br />
: should <hask><*></hask> be named <hask>*>></hask>? the current is symmetric-looking but the meaning is not. --[[User:Uchchwhash|Pirated Dreams]] 20:37, 22 January 2007 (UTC)<br />
:: The <hask>Applicative</hask> class in the <hask>Control.Applicative</hask> module names this function <hask>(*>)</hask>. I'm not sure if this is better than its name in <hask>Monad</hask> or not. Re: duplicate names; I've thought about this a little, and the same argument could be applied to any class that defines methods in terms of each other. <hask>(<)</hask>, <hask>(<=)</hask>, <hask>(>)</hask>, and <hask>(>=)</hask> could be lifted from <hask>Ord</hask> (and defined in terms of <hask>compare</hask>), <hask>(>>)</hask>/<hask>(*>)</hask> from <hask>Applicative</hask>, <hask>join</hask> from <hask>Monad</hask>, etc. I'm not sure where to draw the line, so I'd defer it. [[User:Nmessenger|Nick Messenger]] 16:45, 3 February 2007 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=10588The Other Prelude2007-01-20T07:37:03Z<p>Nmessenger: Imported Prelude(id, const), now it compiles.</p>
<hr />
<div>== Call For Contribution ==<br />
<br />
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.<br />
<br />
== Committee ==<br />
<br />
This project has no committee whatsoever. Issues are discussed on [[Talk:The Other Prelude|the talk page]].<br />
<br />
== Naming Conventions ==<br />
<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
<br />
* Should <hask>Functor</hask> imply <hask>Monad</hask> or the other way around?<br />
* When the same function has an infix and a prefix implementation, should one of them be outside the class to enforce consistency?<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
* The current proposal lacks a well thought <hask>fail</hask> mechanism. Should it be integrated into <hask>MonadZero</hask>, or have a class of his own, or remain in the <hask>Monad</hask> class?<br />
<br />
== Reality ==<br />
<br />
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.<br />
<br />
== The Code ==<br />
<br />
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.<br />
<br />
The imaginary Prelude as it stands,<br />
<br />
=== <hask>TheOtherPrelude.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude where<br />
<br />
import Prelude (id, const) -- hide everything<br />
<br />
-- The idea is to rename 'fmap'.<br />
-- Both map :: (a -> b) -> [a] -> [b] (in []) <br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) (in (->) e)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
class Functor f where<br />
map :: (a -> b) -> f a -> f b<br />
<br />
(.) :: (Functor f) => (a -> b) -> f a -> f b<br />
(.) = map -- defined outside the class as an infix synonym for map.<br />
<br />
-- The following has been shamelessly copied from the<br />
-- Functor hierarchy proposal page (see links below).<br />
class (Functor p) => Applicative p where<br />
-- Minimal complete definition: return and (<*>).<br />
return :: a -> p a -- value lifting<br />
(<*>) :: p (a -> b) -> p a -> p b -- lifted application<br />
(>>) :: p a -> p b -> p b -- when the second is independent of the first<br />
<br />
-- Default definition:<br />
f >> g = (map (const id) f) <*> g<br />
<br />
apply :: (Applicative p) => p (a -> b) -> p a -> p b<br />
apply = (<*>) -- defined outside the class as a prefix synonym for (<*>).<br />
<br />
class (Applicative m) => Monad m where<br />
-- Minimal complete definition: one of join or (>>=).<br />
(>>=) :: m a -> (a -> m b) -> m b -- bind<br />
join :: m (m a) -> m a -- combining levels of structure<br />
<br />
-- Default definitions:<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
-- We shamelessly copy from the MonadPlus reform proposal (link below) now.<br />
-- 'zero' will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
-- Should satisfy 'left zero': zero >>= f = zero<br />
class (Monad mz) => MonadZero mz where<br />
zero :: mz a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero ++ b = b; b ++ zero = b; (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution':<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
class (MonadZero mp) => MonadPlus mp where<br />
(++) :: mp a -> mp a -> mp a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero `orElse` b = b; b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch':<br />
-- (return a) `orElse` b = a<br />
class (MonadZero mo) => MonadOr mo where<br />
orElse :: mo a -> mo a -> mo a<br />
</haskell><br />
<br />
=== <hask>TheOtherPrelude/Utilities.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude.Utilities where<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
</haskell><br />
<br />
== How To Use ==<br />
<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude ()<br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude<br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M<br />
</haskell><br />
<br />
== See also ==<br />
<br />
* [[Class system extension proposal]] - Makes this proposal worth reading at last<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [http://haskell.org/hawiki/NotJustMaybe NotJustMaybe] - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.<br />
<br />
[[Category:Proposals]]<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=10581The Other Prelude2007-01-19T23:54:33Z<p>Nmessenger: Added signatures to sidestep MMR</p>
<hr />
<div>== Call For Contribution ==<br />
<br />
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.<br />
<br />
== Committee ==<br />
<br />
This project has no committee whatsoever. Issues are discussed on [[Talk:The Other Prelude|the talk page]].<br />
<br />
== Naming Conventions ==<br />
<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
<br />
* Should <hask>Functor</hask> imply <hask>Monad</hask> or the other way around?<br />
* When the same function has an infix and a prefix implementation, should one of them be outside the class to enforce consistency?<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
* The current proposal lacks a well thought <hask>fail</hask> mechanism. Should it be integrated into <hask>MonadZero</hask>, or have a class of his own, or remain in the <hask>Monad</hask> class?<br />
<br />
== Reality ==<br />
<br />
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.<br />
<br />
== The Code ==<br />
<br />
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.<br />
<br />
The imaginary Prelude as it stands,<br />
<br />
=== <hask>TheOtherPrelude.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude where<br />
<br />
import Prelude () -- hide everything<br />
<br />
-- The idea is to rename 'fmap'.<br />
-- Both map :: (a -> b) -> [a] -> [b] (in []) <br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) (in (->) e)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
class Functor f where<br />
map :: (a -> b) -> f a -> f b<br />
<br />
(.) :: (Functor f) => (a -> b) -> f a -> f b<br />
(.) = map -- defined outside the class as an infix synonym for map.<br />
<br />
-- The following has been shamelessly copied from the<br />
-- Functor hierarchy proposal page (see links below).<br />
class (Functor p) => Applicative p where<br />
-- Minimal complete definition: return and (<*>).<br />
return :: a -> p a -- value lifting<br />
(<*>) :: p (a -> b) -> p a -> p b -- lifted application<br />
(>>) :: p a -> p b -> p b -- when the second is independent of the first<br />
<br />
-- Default definition:<br />
f >> g = (map (const id) f) <*> g<br />
<br />
apply :: (Applicative p) => p (a -> b) -> p a -> p b<br />
apply = (<*>) -- defined outside the class as a prefix synonym for (<*>).<br />
<br />
class (Applicative m) => Monad m where<br />
-- Minimal complete definition: one of join or (>>=).<br />
(>>=) :: m a -> (a -> m b) -> m b -- bind<br />
join :: m (m a) -> m a -- combining levels of structure<br />
<br />
-- Default definitions:<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
-- We shamelessly copy from the MonadPlus reform proposal (link below) now.<br />
-- 'zero' will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
-- Should satisfy 'left zero': zero >>= f = zero<br />
class (Monad mz) => MonadZero mz where<br />
zero :: mz a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero ++ b = b; b ++ zero = b; (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution':<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
class (MonadZero mp) => MonadPlus mp where<br />
(++) :: mp a -> mp a -> mp a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero `orElse` b = b; b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch':<br />
-- (return a) `orElse` b = a<br />
class (MonadZero mo) => MonadOr mo where<br />
orElse :: mo a -> mo a -> mo a<br />
</haskell><br />
<br />
=== <hask>TheOtherPrelude/Utilities.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude.Utilities where<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
</haskell><br />
<br />
== How To Use ==<br />
<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude ()<br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude<br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M<br />
</haskell><br />
<br />
== See also ==<br />
<br />
* [[Class system extension proposal]] - Makes this proposal worth reading at last<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [http://haskell.org/hawiki/NotJustMaybe NotJustMaybe] - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.<br />
<br />
[[Category:Proposals]]<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=10580The Other Prelude2007-01-19T23:49:15Z<p>Nmessenger: Formatting, small code changes, moved method synonyms outside classes to enforce consistency (choices were arbitrary, change if you want)</p>
<hr />
<div>== Call For Contribution ==<br />
<br />
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.<br />
<br />
== Committee ==<br />
<br />
This project has no committee whatsoever. Issues are discussed on [[Talk:The Other Prelude|the talk page]].<br />
<br />
== Naming Conventions ==<br />
<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
<br />
* Should <hask>Functor</hask> imply <hask>Monad</hask> or the other way around?<br />
* When the same function has an infix and a prefix implementation, should one of them be outside the class to enforce consistency?<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
* The current proposal lacks a well thought <hask>fail</hask> mechanism. Should it be integrated into <hask>MonadZero</hask>, or have a class of his own, or remain in the <hask>Monad</hask> class?<br />
<br />
== Reality ==<br />
<br />
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.<br />
<br />
== The Code ==<br />
<br />
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.<br />
<br />
The imaginary Prelude as it stands,<br />
<br />
=== <hask>TheOtherPrelude.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude where<br />
<br />
import Prelude () -- hide everything<br />
<br />
-- The idea is to rename 'fmap'.<br />
-- Both map :: (a -> b) -> [a] -> [b] (in []) <br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) (in (->) e)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
class Functor f where<br />
map :: (a -> b) -> f a -> f b<br />
<br />
(.) = map -- defined outside the class as an infix synonym for map.<br />
<br />
-- The following has been shamelessly copied from the<br />
-- Functor hierarchy proposal page (see links below).<br />
class (Functor p) => Applicative p where<br />
-- Minimal complete definition: return and (<*>).<br />
return :: a -> p a -- value lifting<br />
(<*>) :: p (a -> b) -> p a -> p b -- lifted application<br />
(>>) :: p a -> p b -> p b -- when the second is independent of the first<br />
<br />
-- Default definition:<br />
f >> g = (map (const id) f) <*> g<br />
<br />
apply = (<*>) -- defined outside the class as a prefix synonym for (<*>).<br />
<br />
class (Applicative m) => Monad m where<br />
-- Minimal complete definition: one of join or (>>=).<br />
(>>=) :: m a -> (a -> m b) -> m b -- bind<br />
join :: m (m a) -> m a -- combining levels of structure<br />
<br />
-- Default definitions:<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
-- We shamelessly copy from the MonadPlus reform proposal (link below) now.<br />
-- 'zero' will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
-- Should satisfy 'left zero': zero >>= f = zero<br />
class (Monad mz) => MonadZero mz where<br />
zero :: mz a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero ++ b = b; b ++ zero = b; (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution':<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
class (MonadZero mp) => MonadPlus mp where<br />
(++) :: mp a -> mp a -> mp a<br />
<br />
-- Should satisfy 'monoid':<br />
-- zero `orElse` b = b; b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch':<br />
-- (return a) `orElse` b = a<br />
class (MonadZero mo) => MonadOr mo where<br />
orElse :: mo a -> mo a -> mo a<br />
</haskell><br />
<br />
=== <hask>TheOtherPrelude/Utilities.hs</hask> ===<br />
<br />
<haskell><br />
module TheOtherPrelude.Utilities where<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
</haskell><br />
<br />
== How To Use ==<br />
<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude ()<br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude<br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M<br />
</haskell><br />
<br />
== See also ==<br />
<br />
* [[Class system extension proposal]] - Makes this proposal worth reading at last<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [http://haskell.org/hawiki/NotJustMaybe NotJustMaybe] - Instead of writing inside a specific monad (i.e. Maybe) write functions generalized on (Monad m)=> where possible.<br />
<br />
[[Category:Proposals]]<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=HaskellWiki:Syntax_highlighting&diff=10015HaskellWiki:Syntax highlighting2007-01-10T05:19:43Z<p>Nmessenger: linked to GeSHi file</p>
<hr />
<div>'''Syntax highlighting''' works for a bunch of languages including Haskell, using [http://qbnz.com/highlighter/ GeSHi] and [http://codersbase.com/index.php/Geshi_haskell Jason Dagit's Haskell file], somewhat modified. <br />
<br />
== Block formatting with <code>&lt;haskell&gt;</code> ==<br />
<br />
To highlight syntax of a block of Haskell, enclose it in <code>&lt;haskell&gt;</code>...<code>&lt;/haskell&gt;</code>. This uses the <code>&lt;pre&gt;</code> element. For instance:<br />
<br />
<haskell><br />
{-<br />
My program<br />
-}<br />
import Prelude<br />
<br />
foo :: (Monad m) => m (Int,Int)<br />
foo = (x-2,x - 1) where<br />
x = 3<br />
<br />
-- The main function<br />
main :: IO ()<br />
main = do<br />
a <- foo<br />
putStr ("And the answer is: " ++(show (fst a))++"\n")<br />
</haskell><br />
<br />
== Inline formatting with <code>&lt;hask&gt;</code> ==<br />
<br />
To highlight syntax of inline Haskell snippets, enclose the span in <code>&lt;hask&gt;</code>...<code>&lt;/hask&gt;</code>. This uses the <code>&lt;code&gt;</code> element, which is inline. For instance: <hask>import Prelude</hask>.<br />
<br />
Inline highlighting is a bit of a hack at the moment, and may be buggy.<br />
<br />
== Styles ==<br />
<br />
For Haskell (only) I have deliberately removed all formatting apart from foreground colour, and those I have tried to keep dark so as not to be visually distracting.<br />
<br />
This is what I am trying to achieve:<br />
<br />
* comments: grey<br />
* keywords (including symbols): blue<br />
* value literals: dark green<br />
* known value identifiers (including symbols): green<br />
* known type identifiers: red<br />
* known classes: purple<br />
* known modules: brown<br />
<br />
I also indent the entire block by 2em. See [[MediaWiki:Common.css]].<br />
<br />
&mdash;[[User:Ashley Y|Ashley Y]] 10:49, 19 March 2006 (UTC)<br />
<br />
== Other languages ==<br />
<br />
This works for certain other languages too. For lisp, for instance, use <code>&lt;pre-lisp&gt;</code>...<code>&lt;/pre-lisp&gt;</code> to format a block of lisp, and <code>&lt;code-lisp&gt;</code>...<code>&lt;/code-lisp&gt;</code> to format text inline. <code>&lt;haskell&gt;</code> is the same as <code>&lt;pre-haskell&gt;</code> and <code>&lt;hask&gt;</code> is the same as <code>&lt;code-haskell&gt;</code>.</div>Nmessengerhttps://wiki.haskell.org/index.php?title=MonadPlus_reform_proposal&diff=9881MonadPlus reform proposal2007-01-04T00:26:56Z<p>Nmessenger: added pretty colors!</p>
<hr />
<div>The [[MonadPlus]] class is ambiguous: while all instances satisfy '''Monoid''' and '''Left Zero''', some such as <tt>[]</tt> satisfy '''Left Distribution''', while others such as <tt>Maybe</tt> and <tt>IO</tt> satisfy '''Left Catch'''.<br />
<br />
== Proposal ==<br />
<br />
It is proposed that MonadPlus be split like this:<br />
<br />
=== MonadZero ===<br />
<br />
<haskell><br />
class Monad m => MonadZero m where<br />
mzero :: m a<br />
</haskell><br />
<br />
satisfying '''Left Zero''':<br />
<br />
<haskell><br />
mzero >>= k = mzero<br />
</haskell><br />
<br />
=== MonadPlus ===<br />
<br />
<haskell><br />
class MonadZero m => MonadPlus m where<br />
mplus :: m a -> m a -> m a<br />
</haskell><br />
<br />
satisfying '''Monoid''' and '''Left Distribution''':<br />
<br />
<haskell><br />
mplus mzero b = b<br />
mplus a mzero = a<br />
mplus (mplus a b) c = mplus a (mplus b c)<br />
mplus a b >>= k = mplus (a >>= k) (b >>= k)<br />
</haskell><br />
<br />
=== MonadOr ===<br />
<br />
<haskell><br />
class MonadZero m => MonadOr m where<br />
morelse :: m a -> m a -> m a<br />
</haskell><br />
<br />
satisfying '''Monoid''' and '''Left Catch''':<br />
<br />
<haskell><br />
morelse mzero b = b<br />
morelse a mzero = a<br />
morelse (morelse a b) c = morelse a (morelse b c)<br />
morelse (return a) b = return a<br />
</haskell><br />
<br />
== Instances of both ==<br />
<br />
Some types could be made instances of both. For instance:<br />
<br />
<haskell><br />
instance MonadOr [] where<br />
morelse [] b = b<br />
morelse a b = a<br />
</haskell><br />
<br />
[[Category:Proposals]] [[Category:Monad]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=User:Uchchwhash&diff=9879User:Uchchwhash2007-01-04T00:10:18Z<p>Nmessenger: reply on Talk:The Other Prelude</p>
<hr />
<div>I am ''Imam Tashdid ul Alam'', a physics undergrad at [http://www.unsw.edu.au UNSW], [http://www.wikipedia.org/wiki/Australia Australia], but by the looks of my monotonically decreasing grades, I'm not sure for how long I will be there.<br />
<br />
A Haskell enthusiastic, a forever newbie, I don't ''do'' Haskell partly because I never took a computing course (officially), and partly because Haskell is cryptic. Yes, cryptic. Even though it has the most lucid lexical and syntactical structure.<br />
<br />
I write Java code occasionally (again, for no particular reason, this "new generation"... they are so... lost!) and therefore crave for the functional approach.<br />
<br />
My love for Haskell is difficult to explain, I know that because I tried to explain it to my friends every now and then, but I think the reason is that Haskell was the first programming language I came across that took the propositions-as-types (or programs-as-proofs) principle seriously.<br />
<br />
So here is my own understanding and criticism of the language.<br />
<br />
== Errors ==<br />
Part of life (...sigh...). Haskell is particularly rough here, as far as I can tell. Whenever there is an <hask>error "I don\'t know what to do here!"</hask> occurs, the program terminates abruptly. This is bad. <br />
<br />
Bad, both computationally and logically. Under the isomorphism, <math>\bot</math> ("bottom", or, it's counterpart in Haskell <hask>undefined</hask>, equivalent to non-termination), is reminiscent of an error. Behold! <hask>error</hask> and <hask>undefined</hask> have the respective types <hask>String -> a</hask> and <hask>a</hask>, which is not at all funny. If you can prove absurdity (if you have a value of a type that is not inhibited) then you can prove everything, they say. <br />
<br />
The designers of Haskell seems to have concluded that making the language logically sound is too hard and they should give it up. They were right. <br />
<br />
Now, when you cannot return a value, what type would be the returned value then? Obviously it should have the type <math>\bot</math>, which does not have a value. So in Haskell, it makes sense to type it as <hask>a</hask>, as you better leave any attempts to type it, since there is no type called <math>\bot</math>, and there is no type without a value (but... but...)<br />
<br />
It just struck me that contructive type thoery is not necessarily extensional. Instead of having just one <math>\bot</math> you can have several phantom types, each one being a distinguishable error. I was so inspired by Ben Rudiak-Gould et al's [http://research.microsoft.com/~simonpj/papers/not-not-ml/index.htm Haskell is not not ML] paper (and Philip Wadler's [http://homepages.inf.ed.ac.uk/wadler/topics/dual.html dual calculus]), but nobody seems to be too serious about them. To be totally honest, I have no clue what they talk about. <br />
<br />
Even then, my pricipal motivation for going through this pain of writing this down is that in Haskell we have a computing interpretation of all the logical operators (although, interpreting <math>\and</math> is a bit vague because of currying), bar the <math>\neg</math>. Why be partial? :-)<br />
<br />
So what I am asking for is a systematic approach to error handling built into the language (not just passing a exeption handler to every function). This is not a Haskell' wish, as Haskell' is not ready for this.<br />
<br />
:The advantage of this approach is you can write recursive functions. For instance:<br />
<br />
<haskell><br />
power2 0 = 1<br />
power2 n = 2 * (power2 (n - 1))<br />
</haskell><br />
<br />
:You see how <hask>power2</hask> refers to itself? It's the exact same mechanism that allows to write<br />
<br />
<haskell><br />
fix f = let x = f x in x<br />
</haskell><br />
<br />
:You'll notice <hask>fix</hask> has type <hask>(a -> a) -> a</hask>, which is usually known as the fallacy of circular reasoning. But if we forbid it, we can't have recursive functions. &mdash;[[User:Ashley Y|Ashley Y]] 08:42, 9 June 2006 (UTC)<br />
:: I am aware of that, I was just trying to promote continuations as negations point of view. I like it very much. --[[User:Uchchwhash|Pirated Dreams]] 14:31, 18 November 2006 (UTC)<br />
<br />
* I made a reply on [[Talk:The Other Prelude]]. You proposed <hask>flatMap</hask>. For consistency, <hask>joinMap</hask> strikes me as better. [[User:Nmessenger|Nick Messenger]] 00:10, 4 January 2007 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=Talk:The_Other_Prelude&diff=9878Talk:The Other Prelude2007-01-04T00:05:37Z<p>Nmessenger: RE: flatMap</p>
<hr />
<div>i have no idea what i'm talking about here, but shouldn't "Monad m" imply "Functor m" if we're already starting with a clean slate? Also, what should the solution to "head", etc be? --[[User:JohannesAhlmann|Johannes Ahlmann]] 09:47, 21 December 2006 (UTC)<br />
:"Monad m" should imply "Functor m". By your question about "head", do you mean the problem of it being undefined on <hask>[]</hask>? [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
:: <hask>head</hask>, <hask>fst</hask> et cetera are projection functions. They can, in fact, be achieved by pattern matching, and are done that way often. It seems to me that at least the Prelude should be very mathematical and leave them out. YMMV. But <hask>Monad m</hask> should really imply <hask>Functor m</hask> if we want to be mathematical, and indeed we do. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
:: I'm not so sure whether you can just leave projections out of the prelude and it definitely wouldn't solve the underlying problem. Also I'd love to see some functions from MissingH (especially a sensible "split") in the prelude. Furthermore there's the question which functions from other libraries should be exported by Prelude (either, list functions, error/catch, fail, fmap, IO functions, mapM, maybe, read/reads, sequence, Numeric functions, ...). There definitely has to be some discussion about the necessity of including some of these. --[[User:JohannesAhlmann|Johannes Ahlmann]] 12:34, 23 December 2006 (UTC)<br />
<br />
==Naming==<br />
Although the name of the page "The Other Prelude" does not seem to fit the Wiki standard (sentence case says: The other prelude), I left it as it appears to be a proper name when you read the content. [[User:BrettGiles|BrettGiles]] 14:13, 21 December 2006 (UTC)<br />
: Yes Brett, at least that was my intention. --[[User:Uchchwhash|Pirated Dreams]] 22:33, 21 December 2006 (UTC)<br />
<br />
== Issues ==<br />
I propose the following:<br />
* The Functor hierarchy proposal should be adopted.<br />
* There will be basic algebra modules in the Prelude hierarchy. Named, possibly, <hask>TheOtherPrelude.Algebra</hask>, if the numerical prelude people are happy with it. At this point I think the name, though clear, is very long. <br />
* I propose operators to be preferred over alphanumeric names. <hask>(++)</hask> seems way cooler than <hask>M.plus</hask>. YMMV. Vote here. About the precedence issue, I think proper usage of parentheses is enough for all practical purposes. Besides, (++) is associative.<br />
* <hask>join</hask> is the same as more specific <hask>concat</hask> as far as I get it. The task it accomplishes is more accurately described by the English word "join" than pseudoEnglish "concat". I think there should be no "concat" at all. One of the principle goals of this project is reducing the API.<br />
* This is basically a question... (>>=) is equivalent to <hask>concatMap</hask> in the list monad. I am not exactly a fan of the name, the Scala community uses <hask>flatMap</hask> as far as I recall. Should we include the function <hask>flatMap</hask> in the monad? Has one advantage, sometimes it's intuitive. I reckon it's intuitive whenever (=<<) is.<br />
** If we really want to go for consistency, then perhaps 'joinMap'? [[User:Nmessenger|Nmessenger]] 00:05, 4 January 2007 (UTC)<br />
--[[User:Uchchwhash|Pirated Dreams]] 12:38, 28 December 2006 (UTC)</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=9864The Other Prelude2007-01-02T17:57:51Z<p>Nmessenger: Pulled (>>) into Applicative. Performance seems less of a concern than generality, IMO, for this exercise. Or is Applicative.(>>) strictly invalid?</p>
<hr />
<div>[[Category:Proposals]]<br />
<br />
== Call For Contribution ==<br />
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.<br />
<br />
== Committee ==<br />
This project has no committee whatsoever. Haskell community discussed the issues [[Talk:The Other Prelude|here]].<br />
<br />
== Naming Conventions ==<br />
* Function names should be easy for beginners to consume. <br />
* Specifically, ''The Other Prelude'' naming convention is to use <br />
** descriptive symbols for functions that are naturally infix (''e.g.'', <hask>mplus</hask> is replaced by <hask>(++)</hask>) <br />
** whole English words and camelCase for functions (''e.g.'', <hask>orElse</hask> but not <hask>fmap</hask>)<br />
<br />
== The Hierarchy ==<br />
Although, not Haskell 98, hierarchical modules will definitely be in Haskell'. We take it for granted.<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Utilities</hask> - Convenient definitions. The reasoning behind its existence is that we want the Prelude to be very concise. It should not steal good names.<br />
<br />
== Open Issues ==<br />
* Should Prelude functions use <hask>Integer</hask> instead of <hask>Int</hask>?<br />
* Should <hask>String</hask> be a class rather than a type synonym?<br />
<br />
== The Code ==<br />
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.<br />
<br />
The imaginery Prelude as it stands,<br />
=== <hask>TheOtherPrelude</hask> ===<br />
<haskell><br />
-- module: TheOtherPrelude<br />
import Prelude () -- hide everything<br />
<br />
<br />
-- the idea is to remove 'fmap'.<br />
-- both map :: (a -> b) -> [a] -> [b] ('fmap' for the monad []) <br />
-- and (.) :: (a -> b) -> (e -> a) -> (e -> b) ('fmap' for the (->) e monad)<br />
-- are good names, and are intuitively prefix and infix respectively.<br />
class Functor f where<br />
-- 'fmap' is guilty of nothing but a bad name<br />
map, (.) :: (a -> b) -> f a -> f b<br />
<br />
-- implementing either is enough<br />
map = (.)<br />
(.) = map<br />
<br />
<br />
-- the following has been shamelessly copied,<br />
-- from the Functor hierarchy proposal[1] wiki page.<br />
class Functor f => Applicative f where<br />
-- lifting a value<br />
return :: a -> f a<br />
<br />
-- should this be named 'ap'? is 'ap' a good name?<br />
-- can you come up with a better name?<br />
-- can it refactor the liftM* type gymnastics?<br />
(<*>) :: f (a -> b) -> f a -> f b <br />
<br />
-- when the second is independent of the first<br />
(>>) :: m a -> m b -> m b<br />
<br />
-- is there a better definition?<br />
fa >> fb = (map (const id) fa) <*> fb<br />
<br />
<br />
-- this leaves little left for the actual Monad class<br />
class Applicative m => Monad m where<br />
-- the binding operation, gist of a monad <br />
(>>=) :: m a -> (a -> m b) -> m b<br />
<br />
-- throwing out the outer monad<br />
join :: m (m a) -> m a<br />
<br />
-- intuitive definitions<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
<br />
-- we shamelessly copy from the MonadPlus reform proposal[2] now.<br />
<br />
-- zero will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
<br />
-- should satisfy 'left zero': zero >>= f = zero<br />
class Monad m => MonadZero m where<br />
zero :: m a<br />
<br />
<br />
-- should satisfy 'monoid' <br />
-- zero ++ b = b, b ++ zero = b, (a ++ b) ++ c = a ++ (b ++ c)<br />
-- and 'left distribution'<br />
-- (a ++ b) >>= f = (a >>= f) ++ (b >>= f)<br />
class MonadZero m => MonadPlus m where<br />
(++) :: m a -> m a -> m a<br />
<br />
<br />
-- should satisfy 'monoid' <br />
-- zero `orElse` b = b, b `orElse` zero = b<br />
-- (a `orElse` b) `orElse` c = a `orElse` (b `orElse` c)<br />
-- and 'left catch'<br />
-- (return a) `orElse` b = a<br />
class MonadZero m => MonadOr m where<br />
orElse :: m a -> m a -> m a<br />
</haskell><br />
<br />
[1]: [[Functor hierarchy proposal]]<br /><br />
[2]: [[MonadPlus reform proposal]]<br />
<br />
=== <hask>TheOtherPrelude.Utilities</hask> ===<br />
<haskell><br />
-- module: TheOtherPrelude.Utilities<br />
<br />
import Prelude () -- hide everything<br />
<br />
-- this is the if-then-else proposal<br />
-- the name has been chosen to reflect the magic of Church booleans!<br />
boolean True x _ = x<br />
boolean False _ y = y<br />
<br />
</haskell><br />
== How To Use ==<br />
<haskell><br />
-- ''The Other Prelude'' is an alternative, not a replacement.<br />
-- So we need to hide everything from the Prelude<br />
import Prelude () <br />
<br />
-- This is just an example assuming there is nothing to hide<br />
import TheOtherPrelude <br />
<br />
-- Hopefully, this module will contain lift,...<br />
-- Standard convention is to use M.lift (instead of liftM)<br />
import qualified TheOtherPrelude.Monad.Kleisli as M <br />
</haskell><br />
<br />
== See also ==<br />
* [[Mathematical prelude discussion]] - A numeric Prelude in good shape already. Will a merger be ever possible?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike ''The Other Prelude'' they ''enhance'' the Prelude.<br />
* [[Functor hierarchy proposal]] - Making <hask>Monad m</hask> imply <hask>Functor m</hask> (adopted by ''The Other Prelude'').<br />
* [[If-then-else]] - Making <hask>if</hask> a function (partially adopted by ''The Other Prelude'', we are silent on the bigger issue of sugar).<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - Functions "missing" from the Haskell Prelude/libraries.<br />
* [[MonadPlus reform proposal]] - Clarifies ambiguities around MonadPlus laws (adopted by ''The Other Prelude'') <br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=List_function_suggestions&diff=9789List function suggestions2006-12-28T11:09:56Z<p>Nmessenger: General cleanup</p>
<hr />
<div>== Let's fix this ==<br />
<br />
We need these useful functions in Data.List; I'll call them 'split' (and variants) and 'replace'. These are easily implemented but everyone always reinvents them. The goal is clarity/uniformity (everyone uses them widely and recognizes them) and portability (I don't have to keep reimplementing these or copying that one file UsefulMissingFunctions.hs).<br />
<br />
Use this page to record consensus as reached on the Talk Page. (Use four tildes to sign your post automatically with your name/timestamp.) Diverging opinions welcome! Note: a lot of good points (diverging opinions!) are covered in the mailing lists, but if we include all these various cases, split* will have 9 variants! I'm working on trying to organize all this into something meaningful.<br />
<br />
== Summary ==<br />
<br />
<i><br />
Hacking up your own custom split (or a tokens/splitOnGlue) must be one<br />
of the most common questions from beginners on the IRC channel.<br />
<br />
Anyone remember what the result of the "let's get split into the base<br />
library" movement's work was?<br />
<br />
ISTR there wasn't a consensus, so nothing happened. Which is silly,<br />
really - I agree we should definitely have a Data.List.split.<br />
</i><br />
<br />
A thread July 2006<br />
<br />
http://www.haskell.org/pipermail/haskell-cafe/2006-July/thread.html#16559<br />
<br />
A thread July 2004<br />
<br />
http://www.haskell.org/pipermail/libraries/2004-July/thread.html#2342<br />
<br />
== Goal ==<br />
<br />
The goal is to reach some kind of reasonable consensus, specifically on naming and semantics. Even if we need pairs of functions to satisfy various usage and algebraic needs. Failing to accommodate every possible use of these functions should not be a sufficient reason to abandon the whole project.<br />
<br />
Note: I (Jared Updike) am working with the belief that efficiency should not be a valid argument to bar these otherwise universally useful functions from the libraries; regexes are overkill for 'split' and 'replace' for common simple situations. Let's assume people will know (or learn) when they need heavier machinery (regexes, FPS/ByteString) and will use it when efficiency is important. We can try to facilitate this by reusing any names from FastPackedString and/or ByteString, etc.<br />
<br />
== The Data.List functions ==<br />
<br />
=== split (working name) ===<br />
<br />
We need a few of these:<br />
<br />
<haskell><br />
split :: Eq a => a -> [a] -> [[a]]<br />
splitWith :: (a -> Bool) -> [a] -> [[a]]<br />
tokens :: (a -> Bool) -> [a] -> [[a]]<br />
</haskell><br />
<br />
That preserve:<br />
<br />
<haskell><br />
join sep . split sep = id<br />
</haskell><br />
<br />
See below for 'join'<br />
<br />
And some that use above split but filter to remove empty elements (but do not preserve above property). Easy enough:<br />
<br />
<haskell><br />
split' :: Eq a => a -> [a] -> [[a]]<br />
splitWith' :: (a -> Bool) -> [a] -> [[a]]<br />
tokens' :: (a -> Bool) -> [a] -> [[a]]<br />
</haskell><br />
<br />
i.e.<br />
<br />
<haskell><br />
split' sep = filter (not . null) . split sep<br />
</haskell><br />
<br />
Usage would be:<br />
<br />
<haskell><br />
tokensws = tokens' (`elem` " \f\v\t\n\r\b")<br />
<br />
tokensws "Hello there\n \n Haskellers! " ==<br />
["Hello", "there", "Haskellers!"]<br />
</haskell><br />
<br />
<i><br />
Would a </i><hask>nonnulls = filter (not . null)</hask><i> function be a better alternative to defining separate filtered splits? [[User:Nmessenger|Nmessenger]] 11:09, 28 December 2006 (UTC)<br />
</i><br />
<br />
'''TODO: add version like python with multi-element separator'''<br />
<br />
'''TODO: give code, copy-paste from threads mentioned above'''<br />
<br />
'''TODO: list names and reasons for/against'''<br />
<br />
=== replace (working name) ===<br />
<br />
<haskell><br />
replace :: [a] -> [a] -> [a] -> [a]<br />
</haskell><br />
<br />
like Python replace:<br />
<br />
<haskell><br />
replace "the" "a" "the quick brown fox jumped over the lazy black dog"<br />
===><br />
"a quick brown fox jumped over a lazy black dog"<br />
</haskell><br />
<br />
'''TODO: give code, copy-paste from threads mentioned above'''<br />
<br />
'''TODO: list names and reasons for/against'''<br />
<br />
=== join (working name) ===<br />
<br />
<haskell><br />
join :: [a] -> [[a]] -> [a]<br />
</haskell><br />
<br />
<haskell><br />
join sep = concat . intersperse sep<br />
</haskell><br />
<br />
'''TODO: copy-paste things from threads mentioned above'''<br />
<br />
'''TODO: list names and reasons for/against'''<br />
<br />
==Function Behavior Changes==<br />
<br />
It is dangerous to change the behavior of prelude functions, however currently unlines will add an additional, unnecessary newline. <hask>unlines . lines</hask> is effectively <hask>(++"\n")</hask> rather than <hask>id</hask>.<br />
<br />
I propose this definition instead:<br />
<br />
<haskell><br />
unlines = concat . intersperse "\n"<br />
</haskell><br />
<br />
Also, lines/words will be effectively defined in terms of split.<br />
<br />
[[Category:Proposals]]<br />
[[Category:Standard libraries]]<br />
[[Category:Idioms]]</div>Nmessengerhttps://wiki.haskell.org/index.php?title=The_Other_Prelude&diff=9788The Other Prelude2006-12-28T09:36:40Z<p>Nmessenger: combined Functor (.) and map type decls</p>
<hr />
<div>[[Category:Proposals]]<br />
<br />
== Call for contribution ==<br />
This fun project, called "The Other Prelude", and is a creative reconstruction of the standard Prelude. By disregarding history and compatibility, we get a clean sheet.<br />
<br />
== Naming conventions ==<br />
The principal is to make the names very readable for both beginners and category theorists (if any).<br />
<br />
== Guidelines ==<br />
* The prelude should not contain any "projection" functions (like <hask>fst</hask> and <hask>snd</hask>. They go to the Extension module.<br />
<br />
<br />
== Issues ==<br />
* Should alphanumeric names be preferred over symbols when defining a class?<br />
* Why do many functions in Prelude use <hask>Int</hask> instead of <hask>Integer</hask>? IMO, <hask>Integer</hask> should be THE preferred datatype for everything (examples: length, splitAt, replicate, drop, take, ...)!<br />
<br />
<br />
== The hierarchy ==<br />
* <hask>TheOtherPrelude</hask> - Minimalistic module.<br />
* <hask>TheOtherPrelude.Extension</hask> - Convenient definitions.<br />
<br />
== The code ==<br />
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.<br />
<br />
The imaginery Prelude as it stands,<br />
<br />
<haskell><br />
import Prelude () -- hide everything<br />
<br />
-- the idea is to remove 'fmap' <br />
-- and map :: (a -> b) -> [a] -> [b] to be a special case<br />
-- as well as having (.) :: (a -> b) -> (e -> a) -> (e -> b) as a<br />
-- special case from the Functor instance for ((->) e)<br />
-- Both notations can be provided to allow for clarity in different situations.<br />
class Functor f where<br />
map, (.) :: (a -> b) -> f a -> f b<br />
map = (.)<br />
(.) = map<br />
<br />
-- the following has been shamelessly copied <br />
-- from the functor hierarchy proposal wiki page<br />
class Functor f => Applicative f where<br />
return :: a -> f a<br />
(<*>) :: f (a -> b) -> f a -> f b -- or should this be named 'ap'? <br />
-- or something even better?<br />
-- could this nice looking function<br />
-- refactor the liftM* idioms?<br />
<br />
(>>) :: f a -> f b -> f b<br />
fa >> fb = (map (const id) fa) <*> fb<br />
<br />
-- this leaves little left for the actual Monad class<br />
class (Applicative m) => Monad m where<br />
(>>=) :: m a -> (a -> m b) -> m b<br />
join :: m (m a) -> m a<br />
<br />
x >>= f = join (map f x)<br />
join x = x >>= id<br />
<br />
-- end of Functor hierarchy dilemma<br />
<br />
-- zero will be used when pattern matching against refutable patterns in<br />
-- do-notation as well as to provide support for monad comprehensions.<br />
class (Monad m) => MonadZero m where<br />
zero :: m a<br />
<br />
class (MonadZero m) => MonadPlus m where<br />
(++) :: m a -> m a -> m a<br />
<br />
class (MonadZero m) => MonadOr m where<br />
orElse :: m a -> m a -> m a<br />
<br />
</haskell><br />
<br />
How to use it, as it stands,<br />
<br />
<haskell><br />
import Prelude () -- hide everything<br />
import TheOtherPrelude -- get everything<br />
import qualified TheOtherPrelude.Monad.Kleisli as M -- standard convention <br />
</haskell><br />
<br />
== See also ==<br />
* [[Mathematical prelude discussion]] - A numeric Prelude. Could this be merged into this one?<br />
* [[Prelude extensions]] and [[Prelude function suggestions]] - Unlike "The Other Prelude" they ''enhance'' the Prelude.<br />
* [[Functor hierarchy proposal]] - making "Monad m" imply "Functor m"<br />
* [[If-then-else]] - making "if" a function<br />
* [http://software.complete.org/missingh/static/doc/ MissingH] - functions "missing" from the haskell Prelude/libraries<br />
<br />
[[Category:Mathematics]]<br />
[[Category:Code]]</div>Nmessenger