packages feed

lhs2tex-1.17: src/StateT.lhs

%-------------------------------=  --------------------------------------------
\subsection{State transformer}
%-------------------------------=  --------------------------------------------

%if codeOnly || showModuleHeader

> module StateT                 (  module StateT  )
> where
>
> import Auxiliaries

%endif

|IO| mit internem Zustand und Fehlerbehandlung.

%if style == math
%format MkXIO (m) = m
%format unXIO (m) = m
%endif

> newtype XIO exc st a          =  MkXIO (st -> IO (Either exc a, st))

%if style /= math

> unXIO (MkXIO f)               =  f

%endif

\NB The state is preserved upon failure.

> instance Functor (XIO exc st) where
>     fmap f m                  =  m >>= \a -> return (f a)
>
> instance Monad (XIO exc st) where
>     return a                  =  MkXIO (\st -> return (Right a, st))
>     m >>= k                   =  MkXIO (\st -> do (r, st') <- unXIO m st
>                                                   case r of
>                                                     Left e  -> return (Left e, st')
>                                                     Right a -> unXIO (k a) st')

\NB We cannot replace |return (Left e, st')| by |return (r, st')| since
the type is not general enough then.

> fetch                         :: XIO exc st st
> fetch                         =  MkXIO (\st -> return (Right st, st))
>
> store                         :: st -> XIO exc st ()
> store st'                     =  MkXIO (\st -> return (Right (), st'))
>
> update                        :: (st -> st) -> XIO exc st ()
> update f                      =  do st <- fetch; store (f st)
>
> toIO                          :: XIO exc st a -> IO a
> toIO m                        =  do (a, _) <- unXIO m undefined; return (fromRight a)
>
> fromIO                        :: IO a -> XIO exc st a
> fromIO m                      =  MkXIO (\st -> do a <- m; return (Right a, st))
>
> raise                         :: exc -> XIO exc st a
> raise e                       =  MkXIO (\st -> return (Left e, st))
>
> try                           :: XIO exc st a -> XIO exc' st (Either exc a)
> try m                         =  MkXIO (\st -> do (r, st') <- unXIO m st; return (Right r, st'))
>
>
> handle                        :: XIO exc st a -> (exc -> XIO exc' st a) -> XIO exc' st a
> handle m h                    =  try m >>= either h return
>
> fromEither                    :: Either exc a -> XIO exc st a
> fromEither                    =  either raise return