%-------------------------------=  --------------------------------------------
\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
