úÎ`«]/      Safe-Inferred provides an  method that invokes the   method of ( multiple times, based on the requested A argument and result type. You will usually have to specify the " type of the argument explicitly.  Note that 0 only works with up to 9 levels of nested monad  transformer.   Safe-Inferred>This function is called to wrap a computation in a tansformed  monad, t m/, with a function that expects an argument and - returns a result of the inner monadic type, m. The canonical 6 example of this is using a monad transformer such as ,  having a computation x ::  MyConfig  a, and $ wanting to wrap a function such as  finally ::  b ->  b  around x to run a cleanup function even when an  exception is thrown. If x invokes a  function such  as ask6, this cannot be accomplished with the ordinary monad  transformer method %. Instead, it can be achieved with:  ) wrap (\op -> op `finally` cleanup) x 7If the inner monad is nested within multiple levels of  transformer, you can invoke wrap multiple times, e.g.: 0 wrap (wrap (\op -> op `finally` cleanup)) x =Sometimes the wrapping function passed as the first argument  of 3 needs to produce its own return value rather than 6 passing one straight through. This is the case with catch.  To do this, use result# to tranlate a pure value into the < inner-monad value required by the outer monad transformer.  (Note that result+ is basically a pure transofmation, but it ? produces a value in the outer monad primarily just so that it = can infer from context what type of result to produce. The > pure value returned must be lifted into the inner monad with  return.) result1 is perhaps best illustrated by example. With a . single level of nesting, use something like:   err <- result Nothing 5 wrap (handle (\(SomeException _) -> return err)) + $ liftM Just $ someIOComputation 8For multiple levels of nesting, you will need to invoke  result multiple times, e.g.:   outerErr <- result Nothing ' innerErr <- lift $ result outerErr A wrap (wrap (handle (\(SomeException _) -> return innerErr))) + $ liftM Just $ someIOComputation Note the use of # so as to compute the inner result ? transformation in the inner monad. Further levels of nesting  require increasing numbers of s. 6It is important to keep in mind that where you invoke result  (or 1) may affect the result. For instance, with the    or !$ transformer, if you return a value  computed with result$, the state will be re-wound to the  point at which you called result, discarding any changes that ( may have taken place in the mean time. resultF4 returns a function that can be used to perform the  same transformation as !. This is necessary if you need < to compute the result type dynamically within the wrapping  function.  can be implemented in terms of resultF  as:   result a = do f <- resultF  return (f a) The example given above for  could altenratively have  been implemented as:   fout <- resultF  fin <- lift resultF  let f = fin . fout D wrap (wrap (handle (\(SomeException _) -> return $ f Nothing))) + $ liftM Just $ someIOComputation &Note that the order of composition is f = fin . fout, and  not f = fout . fin$. This is because types and result = values nest in opposite directions with monad transformers.  Even though & is the inner monad in a type such as  ! "  ()", running any computation of this  type produces a value of type  ((), "). #$%&'()*+,- #$%&'()*+,- Safe-InferredMonadWrapIO is analogous to , but where the wrapping  function is always of type  r ->  r. The point of   MonadWrapIO7 is to go through as many nested monad transformers as  necessary to reach the  monad, so you don't have to keep track 3 of where you are in terms of monad nesting depth. wrapIO is to  as liftIO is to .  resultFIO is to  as liftIO is to . resultIO is to  as liftIO is to .  ./   ./None 0123456789   0123456789 Safe-Inferred is like  MonadWrapIO, but for monads created by  5 transformers. This is useful, if, for example, you  implement your own monad,  ReaderTLike, that is like a ReaderT  except that you don'"t want to make it a member of the  MonadReader % class because you are already using  MonadReader for some D different state (or because you are implementing a library and the + user of the library should be free to use ReaderT).  As long as  ReaderTLike is a member of the  class and  assuming you have a  localLike function equivalent to local, you $ should be able to run things like:  K mwrap (localLike modifyConfig :: ReaderTLike IO a -> ReaderTLike IO a)  someComputation DYou will generally have to specify the type of the wrap function or > computation explicitly, but as long as you specify the type,  ; saves you from keeping track of how many nested levels of 0 transformer you have and from having to invoke  repeatedly. Note one difference from  and  MonadWrapIO is that   and , require an extra argument so as to specify D the inner monad in which you want to supply the result. (E.g., in  the case of using catch( to produce a different return value in . case of exceptions, the inner monad would be , and the extra  argument might be supplied as (undefined ::  Type).  Note that ) only works for up to 9 levels of nested  monad transformer. 1This argument is here just for the type, because  otherwise the  resultTrans has no way of knowing 0 which inner monad you want. The value of this + argument is ignored, so it is safe to use  (undefined :: InnerMonad ()) just as a way of  specifying the type. :;<=>?@ABC :;<=>?@ABCD      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSmonad-wrap-0.1Control.Monad.MultiLiftControl.Monad.WrapControl.Monad.WrapIOControl.Monad.WrapBaseControl.Monad.MultiWrap MultiLiftmlift MonadWrapwrapresultresultF MonadWrapIOwrapIO resultFIOresultIO MonadWrapBasewrapBase resultBase resultFBase MultiWrapmwrapmresultFmresulttransformers-0.3.0.0Control.Monad.Trans.Classlift MonadTrans$fMultiLiftmt9$fMultiLiftmt8$fMultiLiftmt7$fMultiLiftmt6$fMultiLiftmt5$fMultiLiftmt4$fMultiLiftmt3$fMultiLiftmt2$fMultiLiftmt1 $fMultiLiftmmControl.Monad.Trans.ReaderReaderTghc-prim GHC.TypesIOControl.Monad.Trans.State.LazyStateTControl.Monad.Trans.Writer.LazyWriterTbaseGHC.BaseString$fMonadWrapWriterTa(,)$fMonadWrapWriterTa(,)0$fMonadWrapStateTa(,)$fMonadWrapStateTa(,)0$fMonadWrapReaderTaa$fMonadWrapRWSTa(,,)$fMonadWrapRWSTa(,,)0$fMonadWrapMaybeTaMaybe$fMonadWrapListTa[]$fMonadWrapIdentityTaa$fMonadWrapErrorTaEither$fMonadWrapIOtar$fMonadWrapIOIOaa$fMonadWrapBaseSTSTaa$fMonadWrapBaseSTSTaa0$fMonadWrapBaseEitherEitheraa$fMonadWrapBase(->)(->)aa!$fMonadWrapBaseIdentityIdentityaa$fMonadWrapBaseMaybeMaybeaa$fMonadWrapBaseSTMSTMaa$fMonadWrapBaseIOIOaa$fMonadWrapBase[][]aa$fMonadWrapBasetbar$fMultiWrapmt9a9a0$fMultiWrapmt8a8a0$fMultiWrapmt7a7a0$fMultiWrapmt6a6a0$fMultiWrapmt5a5a0$fMultiWrapmt4a4a0$fMultiWrapmt3a3a0$fMultiWrapmt2a2a0$fMultiWrapmt1a1a0$fMultiWrapmmaa