[Haskell-cafe] Newbie Q: Monad 'fail' and 'error'

Tillmann Rendel rendel at rbg.informatik.tu-darmstadt.de
Wed Jun 6 06:56:06 EDT 2007


Dmitri O.Kondratiev wrote:
> Monad class contains declaration
> 
> *fail* :: String -> m a
> 
> and provides default implementation for 'fail' as:
> 
> fail s = error s
> 
> On the other hand Prelude defines:
> *
> error* :: String -> a
> 
> which stops execution and displays an error message.
> 
> Questions:
> 1) What value and type 'error' actually returns in:
> error "some message" ?

For practical purposes:

   typechecking: every type the context asks for.
   execution: no value, because execution stops.

For theoretical purposes, error could be implemented by

   error :: String -> a
   error msg = error msg

with the extra-semantical magical side effect of printing msg and 
aborting execution.

> 2) How declaration
> String -> m a
> matches with
> String -> a ?

Alpha renaming to fresh variables yields

   String -> b c
   String -> d

wich unifies by taking d := b c.

> 3) In Maybe monad:
> fail = Nothing
> 
> When and how 'fail' is used in Maybe monad?

The default fail implementation is not very clever. If something fails, 
execution is aborted and the user is confronted with some error message. 
Some monads support richer error handling schemes. The maybe monad 
encodes a succeeding computation with Just it's result, and a failed 
computation with Nothing.

An example:

-- divBy is a possible failing computation in some monad
divBy :: Monad m => Int -> Int -> m Int
divBy a 0 = fail "div by zero"
divBy a b = return (a `div` b)

-- div by three succeeds
15 `divBy` 3 :: Maybe Int   ~~>   Just 5

-- div by zero fails
15 `divBy` 0 :: Maybe Int   ~~>   Nothing

-- divByAll is a shortcut for a list of divBy's
divByAll :: Monad m => Int -> [Int] -> [m Int]
divByAll a bs = map (divBy a) bs

-- div by all returns a list of computations
15 `divByAll` [3, 0] :: [Maybe Int]   ~~>   [Just 5, Nothing]

-- sequence succeeds if all computations in a list succeeds
sequence (15 `divByAll` [3, 0]) :: Maybe [Int]   ~~>   Nothing
sequence (15 `divByAll` [3, 5]) :: Maybe [Int]   ~~>   Just [5, 3]

divBy, divByAll, sequence do not know anything about Maybe, they work 
for all monads, because they only use >>=, fail and return.

The idea is that Monad defines some general interface for computations, 
and the various Monad instances define the exact behaviour. Maybe's 
behaviour is: if a subcomputation fails, the whole computation fails.

There are other monads. consider the list monad, and it's behaviour: if 
a subcomputation fails, backtrack and try some other alternative.

Tillmann


More information about the Haskell-Cafe mailing list