Thanks for excellent explanation! Examples really help.<br><br>So, in general 'fail' behavior will differ from monad to monad. <br>In this example:<br><br>divBy :: Monad m => Int -> Int -> m Int<br>divBy a 0 = fail "div by zero"
<br>divBy a b = return (a `div` b)<br><br>Default 'fail' implementation in Monad class will be:<br>*DivBy> divBy 5 0<br>Loading package haskell98-1.0 ... linking ... done.<br>*** Exception: user error (div by zero)
<br><br>And when explicitly defining monad as Maybe it will be different:<br>*DivBy> divBy 5 0::Maybe Int<br>Nothing<br><br>I am curious if it is possible to 'cast' divBy to List, Identity, other monads? How?<br>
<br><div><span class="gmail_quote"><br>On 6/6/07, <b class="gmail_sendername">Tillmann Rendel</b> <<a href="mailto:rendel@rbg.informatik.tu-darmstadt.de">rendel@rbg.informatik.tu-darmstadt.de</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Dmitri O.Kondratiev wrote:<br>> Monad class contains declaration<br>><br>> *fail* :: String -> m a<br>><br>> and provides default implementation for 'fail' as:<br>><br>> fail s = error s<br>
><br>> On the other hand Prelude defines:<br>> *<br>> error* :: String -> a<br>><br>> which stops execution and displays an error message.<br>><br>> Questions:<br>> 1) What value and type 'error' actually returns in:
<br>> error "some message" ?<br><br>For practical purposes:<br><br> typechecking: every type the context asks for.<br> execution: no value, because execution stops.<br><br>For theoretical purposes, error could be implemented by
<br><br> error :: String -> a<br> error msg = error msg<br><br>with the extra-semantical magical side effect of printing msg and<br>aborting execution.<br><br>> 2) How declaration<br>> String -> m a<br>> matches with
<br>> String -> a ?<br><br>Alpha renaming to fresh variables yields<br><br> String -> b c<br> String -> d<br><br>wich unifies by taking d := b c.<br><br>> 3) In Maybe monad:<br>> fail = Nothing<br>>
<br>> When and how 'fail' is used in Maybe monad?<br><br>The default fail implementation is not very clever. If something fails,<br>execution is aborted and the user is confronted with some error message.<br>Some monads support richer error handling schemes. The maybe monad
<br>encodes a succeeding computation with Just it's result, and a failed<br>computation with Nothing.<br><br>An example:<br><br>-- divBy is a possible failing computation in some monad<br>divBy :: Monad m => Int -> Int -> m Int
<br>divBy a 0 = fail "div by zero"<br>divBy a b = return (a `div` b)<br><br>-- div by three succeeds<br>15 `divBy` 3 :: Maybe Int ~~> Just 5<br><br>-- div by zero fails<br>15 `divBy` 0 :: Maybe Int ~~> Nothing
<br><br>-- divByAll is a shortcut for a list of divBy's<br>divByAll :: Monad m => Int -> [Int] -> [m Int]<br>divByAll a bs = map (divBy a) bs<br><br>-- div by all returns a list of computations<br>15 `divByAll` [3, 0] :: [Maybe Int] ~~> [Just 5, Nothing]
<br><br>-- sequence succeeds if all computations in a list succeeds<br>sequence (15 `divByAll` [3, 0]) :: Maybe [Int] ~~> Nothing<br>sequence (15 `divByAll` [3, 5]) :: Maybe [Int] ~~> Just [5, 3]<br><br>divBy, divByAll, sequence do not know anything about Maybe, they work
<br>for all monads, because they only use >>=, fail and return.<br><br>The idea is that Monad defines some general interface for computations,<br>and the various Monad instances define the exact behaviour. Maybe's
<br>behaviour is: if a subcomputation fails, the whole computation fails.<br><br>There are other monads. consider the list monad, and it's behaviour: if<br>a subcomputation fails, backtrack and try some other alternative.
<br><br>Tillmann<br></blockquote></div><br><br clear="all"><br><br>