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

%if codeOnly || showModuleHeader

> {-# LANGUAGE GeneralizedNewtypeDeriving #-}
> {-# OPTIONS_GHC -fno-warn-unused-imports #-}
> module StateT                 (  module StateT  )
> where
>
> import Control.Applicative -- only needed for older GHCs
> import Control.Monad.Except
> import Control.Monad.State

%endif

|IO| with internal state and error handling.

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

> newtype XIO exc st a          =  MkXIO (ExceptT exc (StateT st IO) a)
>   deriving (Functor, Applicative, Monad, MonadIO, MonadState st, MonadError exc)

-- XIO exc st a ~= StateT st IO (Either exc a)
--              ~= ErrorT exc (StateT st IO) a

%if style /= math

> unXIO                         :: XIO exc st a -> ExceptT exc (StateT st IO) a
> unXIO (MkXIO f)               =  f

%endif

\NB The state is preserved upon failure.

> toIO                          :: XIO exc st a -> IO a
> toIO (MkXIO m)                =  do
>                                    (r, _) <- runStateT (runExceptT m)
>                                                        (error "no initial state supplied")
>                                    case r of Left  _ -> error "unhandled error"
>                                              Right x -> return x

> fromEither                    :: Either exc a -> XIO exc st a
> fromEither                    =  either throwError return
