{-# LANGUAGE MultiParamTypeClasses #-}{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE FunctionalDependencies #-}{-# LANGUAGE UndecidableInstances #-}moduleControl.Monad.WrapIO(MonadWrapIO(..))whereimportControl.Monad.Trans.ClassimportControl.Monad.Wrap-- | MonadWrapIO is analogous to 'MonadWrap', but where the wrapping-- function is always of type @'IO' r -> 'IO' r@. The point of-- @MonadWrapIO@ is to go through as many nested monad transformers as-- necessary to reach the 'IO' monad, so you don't have to keep track-- of where you are in terms of monad nesting depth.class(Monadm)=>MonadWrapIOmar|ma->rwhere-- | @wrapIO@ is to 'wrap' as 'liftIO' is to 'lift'.wrapIO::(IOr->IOr)->ma->ma-- | @resultFIO@ is to 'resultF' as 'liftIO' is to 'lift'.resultFIO::m(a->r)-- | @resultIO@ is to 'result' as 'liftIO' is to 'lift'.resultIO::a->mrresultIOa=resultFIO>>=return.($a)instanceMonadWrapIOIOaawherewrapIOf=fresultFIO=returnidresultIO=return-- This implementation works for all wrapable monads, but requires-- UndecidableInstances.instance(Monadm,MonadTranst,Monad(tm),MonadWrapIOmarr,MonadWraptaar)=>MonadWrapIO(tm)arwherewrapIOf=wrap(wrapIOf)resultFIO=doouter<-resultFinner<-liftresultFIOreturn$inner.outerresultIOa=resulta>>=lift.resultIO