<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <!--Rendered using the Haskell Html Library v0.2--> <HTML ><HEAD ><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8" ><TITLE >Control.Monad.Error</TITLE ><LINK HREF="haddock.css" REL="stylesheet" TYPE="text/css" ><SCRIPT SRC="haddock-util.js" TYPE="text/javascript" ></SCRIPT ><SCRIPT TYPE="text/javascript" >window.onload = function () {setSynopsis("mini_Control-Monad-Error.html")};</SCRIPT ></HEAD ><BODY ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="topbar" ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD ><IMG SRC="haskell_icon.gif" WIDTH="16" HEIGHT="16" ALT=" " ></TD ><TD CLASS="title" >mtl-1.1.0.2: Monad transformer library</TD ><TD CLASS="topbut" ><A HREF="index.html" >Contents</A ></TD ><TD CLASS="topbut" ><A HREF="doc-index.html" >Index</A ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="modulebar" ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD ><FONT SIZE="6" >Control.Monad.Error</FONT ></TD ><TD ALIGN="right" ><TABLE CLASS="narrow" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="infohead" >Portability</TD ><TD CLASS="infoval" >non-portable (multi-parameter type classes)</TD ></TR ><TR ><TD CLASS="infohead" >Stability</TD ><TD CLASS="infoval" >experimental</TD ></TR ><TR ><TD CLASS="infohead" >Maintainer</TD ><TD CLASS="infoval" >libraries@haskell.org</TD ></TR ></TABLE ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="section4" ><B >Contents</B ></TD ></TR ><TR ><TD ><DL ><DT ><A HREF="#1" >Example 1: Custom Error Data Type </A ></DT ><DT ><A HREF="#2" >Example 2: Using ErrorT Monad Transformer </A ></DT ></DL ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="section1" >Description</TD ></TR ><TR ><TD CLASS="doc" ><DL ><DT >Computation type:</DT ><DD > Computations which may fail or throw exceptions. </DD ><DT >Binding strategy:</DT ><DD > Failure records information about the cause/location of the failure. Failure values bypass the bound function, other values are used as inputs to the bound function. </DD ><DT >Useful for:</DT ><DD > Building computations from sequences of functions that may fail or using exception handling to structure error handling. </DD ><DT >Zero and plus:</DT ><DD > Zero is represented by an empty error and the plus operation executes its second argument if the first fails. </DD ><DT >Example type:</DT ><DD > <TT >Data.Either String a</TT > </DD ></DL ><P >The Error monad (also called the Exception monad). </P ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="section1" >Synopsis</TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="body" ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="decl" >module <A HREF="Control-Monad-Error-Class.html" >Control.Monad.Error.Class</A ></TD ></TR ><TR ><TD CLASS="s8" ></TD ></TR ><TR ><TD CLASS="decl" ><SPAN CLASS="keyword" >newtype</SPAN > <A HREF="#t%3AErrorT" >ErrorT</A > e m a = <A HREF="#v%3AErrorT" >ErrorT</A > {<TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="recfield" ><A HREF="#v%3ArunErrorT" >runErrorT</A > :: m (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e a)</TD ></TR ></TABLE >}</TD ></TR ><TR ><TD CLASS="s8" ></TD ></TR ><TR ><TD CLASS="decl" ><A HREF="#v%3AmapErrorT" >mapErrorT</A > :: (m (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e a) -> n (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e' b)) -> <A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m a -> <A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e' n b</TD ></TR ><TR ><TD CLASS="s8" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="../base/Control-Monad.html" >Control.Monad</A ></TD ></TR ><TR ><TD CLASS="s8" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="../base/Control-Monad-Fix.html" >Control.Monad.Fix</A ></TD ></TR ><TR ><TD CLASS="s8" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="Control-Monad-Trans.html" >Control.Monad.Trans</A ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="section1" >Documentation</TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="Control-Monad-Error-Class.html" >Control.Monad.Error.Class</A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" ><SPAN CLASS="keyword" >newtype</SPAN > <A NAME="t:ErrorT" ><A NAME="t%3AErrorT" ></A ></A ><B >ErrorT</B > e m a </TD ></TR ><TR ><TD CLASS="body" ><TABLE CLASS="vanilla" CELLSPACING="0" CELLPADDING="0" ><TR ><TD CLASS="ndoc" ><P >The error monad transformer. It can be used to add error handling to other monads. </P ><P >The <TT >ErrorT</TT > Monad structure is parameterized over two things: </P ><UL ><LI > e - The error type. </LI ><LI > m - The inner monad. </LI ></UL ><P >Here are some examples of use: </P ><PRE > -- wraps IO action that can throw an error e type ErrorWithIO e a = ErrorT e IO a ==> ErrorT (IO (Either e a)) -- IO monad wrapped in StateT inside of ErrorT type ErrorAndStateWithIO e s a = ErrorT e (StateT s IO) a ==> ErrorT (StateT s IO (Either e a)) ==> ErrorT (StateT (s -> IO (Either e a,s))) </PRE ></TD ></TR ><TR ><TD CLASS="section4" >Constructors</TD ></TR ><TR ><TD CLASS="body" ><TABLE CLASS="vanilla" CELLSPACING="5" CELLPADDING="0" ><TR ><TD CLASS="arg" ><A NAME="v:ErrorT" ><A NAME="v%3AErrorT" ></A ></A ><B >ErrorT</B ></TD ><TD CLASS="rdoc" ></TD ></TR ><TR ><TD CLASS="body" COLSPAN="2" ><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0" ><TR ><TD CLASS="arg" ><A NAME="v:runErrorT" ><A NAME="v%3ArunErrorT" ></A ></A ><B >runErrorT</B > :: m (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e a)</TD ><TD CLASS="rdoc" ></TD ></TR ></TABLE ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="section4" ><IMG SRC="minus.gif" CLASS="coll" ONCLICK="toggle(this,'i:ErrorT')" ALT="show/hide" > Instances</TD ></TR ><TR ><TD CLASS="body" ><DIV ID="i:ErrorT" STYLE="display:block;" ><TABLE CLASS="vanilla" CELLSPACING="1" CELLPADDING="0" ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-RWS-Class.html#t%3AMonadRWS" >MonadRWS</A > r w s m) => <A HREF="Control-Monad-RWS-Class.html#t%3AMonadRWS" >MonadRWS</A > r w s (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-Writer-Class.html#t%3AMonadWriter" >MonadWriter</A > w m) => <A HREF="Control-Monad-Writer-Class.html#t%3AMonadWriter" >MonadWriter</A > w (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-State-Class.html#t%3AMonadState" >MonadState</A > s m) => <A HREF="Control-Monad-State-Class.html#t%3AMonadState" >MonadState</A > s (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-Reader-Class.html#t%3AMonadReader" >MonadReader</A > r m) => <A HREF="Control-Monad-Reader-Class.html#t%3AMonadReader" >MonadReader</A > r (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="../base/Control-Monad.html#t%3AMonad" >Monad</A > m, <A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e) => <A HREF="Control-Monad-Error-Class.html#t%3AMonadError" >MonadError</A > e (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" ><A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e => <A HREF="Control-Monad-Trans.html#t%3AMonadTrans" >MonadTrans</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="../base/Control-Monad.html#t%3AMonad" >Monad</A > m, <A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e) => <A HREF="../base/Control-Monad.html#t%3AMonad" >Monad</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" ><A HREF="../base/Control-Monad.html#t%3AMonad" >Monad</A > m => <A HREF="../base/Control-Monad.html#t%3AFunctor" >Functor</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="../base/Control-Monad-Fix.html#t%3AMonadFix" >MonadFix</A > m, <A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e) => <A HREF="../base/Control-Monad-Fix.html#t%3AMonadFix" >MonadFix</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="../base/Control-Monad.html#t%3AMonad" >Monad</A > m, <A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e) => <A HREF="../base/Control-Monad.html#t%3AMonadPlus" >MonadPlus</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-Trans.html#t%3AMonadIO" >MonadIO</A > m) => <A HREF="Control-Monad-Trans.html#t%3AMonadIO" >MonadIO</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ><TR ><TD CLASS="decl" >(<A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A > e, <A HREF="Control-Monad-Cont-Class.html#t%3AMonadCont" >MonadCont</A > m) => <A HREF="Control-Monad-Cont-Class.html#t%3AMonadCont" >MonadCont</A > (<A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m)</TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" ><A NAME="v:mapErrorT" ><A NAME="v%3AmapErrorT" ></A ></A ><B >mapErrorT</B > :: (m (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e a) -> n (<A HREF="../base/Data-Either.html#t%3AEither" >Either</A > e' b)) -> <A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e m a -> <A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A > e' n b</TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="../base/Control-Monad.html" >Control.Monad</A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="../base/Control-Monad-Fix.html" >Control.Monad.Fix</A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="decl" >module <A HREF="Control-Monad-Trans.html" >Control.Monad.Trans</A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="section1" ><A NAME="1" ><A NAME="1" >Example 1: Custom Error Data Type </A ></A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="doc" ><P >Here is an example that demonstrates the use of a custom <TT ><A HREF="Control-Monad-Error-Class.html#t%3AError" >Error</A ></TT > data type with the <TT ><A HREF="Control-Monad-Error-Class.html#v%3AthrowError" >throwError</A ></TT > and <TT ><A HREF="Control-Monad-Error-Class.html#v%3AcatchError" >catchError</A ></TT > exception mechanism from <TT ><A HREF="Control-Monad-Error-Class.html#t%3AMonadError" >MonadError</A ></TT >. The example throws an exception if the user enters an empty string or a string longer than 5 characters. Otherwise it prints length of the string. </P ><PRE >-- This is the type to represent length calculation error. data LengthError = EmptyString -- Entered string was empty. | StringTooLong Int -- A string is longer than 5 characters. -- Records a length of the string. | OtherError String -- Other error, stores the problem description. -- We make LengthError an instance of the Error class -- to be able to throw it as an exception. instance Error LengthError where noMsg = OtherError "A String Error!" strMsg s = OtherError s -- Converts LengthError to a readable message. instance Show LengthError where show EmptyString = "The string was empty!" show (StringTooLong len) = "The length of the string (" ++ (show len) ++ ") is bigger than 5!" show (OtherError msg) = msg -- For our monad type constructor, we use Either LengthError -- which represents failure using Left LengthError -- or a successful result of type a using Right a. type LengthMonad = Either LengthError main = do putStrLn "Please enter a string:" s <- getLine reportResult (calculateLength s) -- Wraps length calculation to catch the errors. -- Returns either length of the string or an error. calculateLength :: String -> LengthMonad Int calculateLength s = (calculateLengthOrFail s) `catchError` Left -- Attempts to calculate length and throws an error if the provided string is -- empty or longer than 5 characters. -- The processing is done in Either monad. calculateLengthOrFail :: String -> LengthMonad Int calculateLengthOrFail [] = throwError EmptyString calculateLengthOrFail s | len > 5 = throwError (StringTooLong len) | otherwise = return len where len = length s -- Prints result of the string length calculation. reportResult :: LengthMonad Int -> IO () reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len)) reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e)) </PRE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="section1" ><A NAME="2" ><A NAME="2" >Example 2: Using ErrorT Monad Transformer </A ></A ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="doc" ><P ><TT ><TT ><A HREF="Control-Monad-Error.html#t%3AErrorT" >ErrorT</A ></TT ></TT > monad transformer can be used to add error handling to another monad. Here is an example how to combine it with an <TT >IO</TT > monad: </P ><PRE >import Control.Monad.Error -- An IO monad which can return String failure. -- It is convenient to define the monad type of the combined monad, -- especially if we combine more monad transformers. type LengthMonad = ErrorT String IO main = do -- runErrorT removes the ErrorT wrapper r <- runErrorT calculateLength reportResult r -- Asks user for a non-empty string and returns its length. -- Throws an error if user enters an empty string. calculateLength :: LengthMonad Int calculateLength = do -- all the IO operations have to be lifted to the IO monad in the monad stack liftIO $ putStrLn "Please enter a non-empty string: " s <- liftIO getLine if null s then throwError "The string was empty!" else return $ length s -- Prints result of the string length calculation. reportResult :: Either String Int -> IO () reportResult (Right len) = putStrLn ("The length of the string is " ++ (show len)) reportResult (Left e) = putStrLn ("Length calculation failed with error: " ++ (show e)) </PRE ></TD ></TR ><TR ><TD CLASS="s15" ></TD ></TR ><TR ><TD CLASS="botbar" >Produced by <A HREF="http://www.haskell.org/haddock/" >Haddock</A > version 2.4.2</TD ></TR ></TABLE ></BODY ></HTML >