title: Why were Haskell 98's standard classes made inferior to Haskell 1.3's?
body: <p>Before Haskell 98, there were Haskell 1.0 through 1.4. It's pretty interesting to see the development throughout the years, as features were added to the earliest versions of standardized Haskell.</p>
  
  <p>For instance, the do-notation was first standardized by <a href="http://www.haskell.org/definition/haskell-report-1.3.ps.gz" rel="nofollow">Haskell 1.3</a> (published 1996-05-01). In the <code>Prelude</code>, we find the following definitions (page 87):</p>
  
  <pre><code>-- Monadic classes
  
  class  Functor f  where
      map         :: (a -&gt; b) -&gt; f a -&gt; f b
  
  class  Monad m  where
      (&gt;&gt;=)       :: m a -&gt; (a -&gt; m b) -&gt; m b
      (&gt;&gt;)        :: m a -&gt; m b -&gt; m b
      return      :: a -&gt; m a
  
      m &gt;&gt; k      = m &gt;&gt;= \_ -&gt; k
  
  class  (Monad m) =&gt; MonadZero m  where
      zero        :: m a
  
  class  (MonadZero m) =&gt; MonadPlus m where
      (++)        :: m a -&gt; m a -&gt; m a
  </code></pre>
  
  <p>The same definitions are found in Haskell 1.4. I do have a few problems with this (e.g. the <a href="http://www.haskell.org/haskellwiki/MonadPlus" rel="nofollow"><code>MonadPlus</code> reform</a> hasn't happened here yet), but overall, it is a very nice definition.</p>
  
  <p>This is very different from Haskell 98, where the following definition is found:</p>
  
  <pre><code>-- Monadic classes
  
  
  class  Functor f  where
      fmap              :: (a -&gt; b) -&gt; f a -&gt; f b
  
  
  class  Monad m  where
      (&gt;&gt;=)  :: m a -&gt; (a -&gt; m b) -&gt; m b
      (&gt;&gt;)   :: m a -&gt; m b -&gt; m b
      return :: a -&gt; m a
      fail   :: String -&gt; m a
  
          -- Minimal complete definition:
          --      (&gt;&gt;=), return
      m &gt;&gt; k  =  m &gt;&gt;= \_ -&gt; k
      fail s  = error s
  </code></pre>
  
  <p>This is also the definition in Haskell 2010. I have the following problems with this definition:</p>
  
  <ul>
  <li><code>MonadZero</code> and <code>MonadPlus</code> are gone. They were useful classes.</li>
  <li><p>In case of a pattern match failure in a do-notation...</p>
  
  <ul>
  <li>Haskell 1.3 uses <code>zero</code>. The Left Zero law applies (<code>zero &gt;&gt;= k = zero</code>), so you know what's supposed to happen.</li>
  <li>Haskell 98 uses <code>fail msg</code>, where <code>msg</code> is compiler-generated in case of GHC. Anything can happen, no guarantees about its semantics. Therefore, it's not much of a function for users. <em>As a consequence, the behaviour of pattern match failures in Haskell 98's do-notation is unpredictable!</em></li>
  </ul></li>
  <li><p>Names are less general (e.g. <code>map</code> vs. <code>fmap</code>). Not a big problem, but it's a thorn in my eye.</p></li>
  </ul>
  
  <hr>
  
  <p>All in all, I think these changes weren't for the best. In fact, I think they were a step backwards from Haskell 1.4. <strong>Why were these things changed for Haskell 98, and why in this way?</strong></p>
  
  <hr>
  
  <p>As an aside, I can imagine the following defenses:</p>
  
  <ul>
  <li><em>"<code>fail</code> allows for locating errors."</em> Only for programmers, and only at runtime. The (unportable!) error message is not exactly something you want to parse. If you really care about it, you should track it explicitly. We now have <code>Control.Failure</code> from the <code>failure</code> package, which does a much better job at this (<code>failure x</code> behaves mostly like <code>zero</code>).</li>
  <li><em>"Having too many classes makes development and use too hard."</em> Having too few classes breaks their laws, and those laws are just as important as types.</li>
  <li><em>"Instance-restricted functions are easier to learn."</em> Then why isn't there a <code>SimplePrelude</code> instead, with most of the classes removed? It's only one magical declaration away for students, they can manage that much. (Perhaps <code>{-# LANGUAGE RebindableSyntax #-}</code> is needed too, but again, students are <em>very</em> good at copy-pasting stuff.)</li>
  <li><em>"Instance-restricted functions make errors more readable."</em> I use <code>fmap</code> much more often than <code>map</code>, so why not <code>map</code> and <code>listMap</code> instead?</li>
  </ul>