Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,263
    • Issues 4,263
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 417
    • Merge Requests 417
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Wiki
    • Design
  • monad fail

Last edited by Takenobu Tani Nov 06, 2020
Page history New page

monad fail

MonadFail

This page contains some notes and ideas that predate the official MonadFail Proposal (MFP) which can be found at

prime:Libraries/Proposals/MonadFail

The Basic Idea

The basic idea is to split the Monad class into

class Applicative m => Monad m where
  (>>=)  :: m a -> (a -> m b) -> m b

  (>>)   :: m a -> m b -> m b
  m >> k = m >>= \_ -> k 

  return :: a -> m a -- still in Monad for historic reasons
  return = pure

class Monad m => MonadFail m where
  fail :: String -> m a

and adapt do-desugaring accordingly. See https://github.com/quchen/articles/blob/master/monad_fail.md for more details.

Misc Ideas

To aid transition, we can keep fail in Monad, and start out with

class Monad m => MonadFail m where
  mfail :: String -> m a

(or maybe even require MonadPlus, as fail _ = mzero is a sensible default). This is a comparable situation as with post-AMP pure/return , where the now redundant return (which is now an alias for pure) is to be phased out into an ordinary top-level (non-method) function in the long term.

The MonadFail(mfail) desugaring of do could then be enabled via a language pragma {-# LANGUAGE MonadFail -#}, allowing for have a future -XHaskell201x to switch that feature on by default, while retaining -XHaskell2010 with the current old Monad(fail) desugaring semantics.

Monad(fail) could default to MonadFail(mfail) via -XDefaultSignatures

History

In Haskell 1.4 (postscript) fail was not part of the Monad class. Instead there was a separate MonadZero class containing the zero operation whose purpose was to handle pattern-failures in do-syntax (akin to what fail does today). Here are the original Haskell 1.4 class definitions quoted from section "6.2.5 Monadic Classes":

class Functor f where
  map :: (a -> b) -> (f a -> f b)

class Monad m where
  (>>=)  :: m a -> (a -> m b) -> m b
  (>>)   :: m a -> m b -> m b
  return :: a -> m a

class (Monad m) => MonadZero m where
  zero :: m a

class (MonadZero m) => MonadPlus m where
  (++) :: m a -> m a -> m a

However, when Haskell 98 was drafted issues with irrefutable patterns lead to MonadZero being folded into the Monad class (but it doesn't seem to have been an unanimous nor easy decision back then).

The issue is highlighted by deconstructing a monadic action returning a single-constructor value:

f :: Monad m => m (a,b) -> m a
f m1 = do { x <- m1; return (fst x) }

g :: ??? m => m (a,b) -> m a
g m1 = do { (a,_) <- m1; return a }

h :: Monad m => m (a,b) -> m a
h m1 = do { ~(a,_) <- m1; return a }

Should ??? for g be Monad or MonadZero? The single-constructor pattern match will never fail ("unfailable"), so zero is never used. In fact, in Haskell 1.4 g would only require Monad, but requires the concept of `"unfailable" pattern matches (in addition to "irrefutable" pattern matches).

Related Concepts/Proposals

  • MonadPlus reform proposal
  • ApplicativeDo
Clone repository

GHC Home
GHC User's Guide

Joining In

Newcomers info
Mailing Lists & IRC
The GHC Team

Documentation

GHC Status Info
Working conventions
Building Guide
Debugging
Commentary

Wiki

Title Index
Recent Changes