### Running Cont Monad Examples Source: https://context7.com/haskell/mtl/llms.txt Shows how to execute computations within the pure `Cont` monad using `runCont` and `evalCont`, and `ContT` using `runContT`. ```haskell main :: IO () main = do -- runCont / evalCont run the pure Cont monad print $ runCont (findFirst [3, 7, 2, 9, 1] (> 6)) id -- Just 7 print $ runCont (findFirst [1, 2, 3] (> 100)) id -- Nothing -- runContT for the transformer runContT countDown pure -- 5 -- 4 -- 3 -- 2 -- 1 -- 0 ``` -------------------------------- ### Running AccumT over IO Example Source: https://context7.com/haskell/mtl/llms.txt Demonstrates running a `MonadAccum` computation stacked over `IO` using `runAccumT`, showing the results and the final accumulated log. ```haskell -- Stacking AccumT over IO exampleT :: IO () exampleT = do (results, finalLog) <- runAccumT (process [10, 20]) [] print results mapM_ putStrLn finalLog ``` -------------------------------- ### Lifting IO action into ExceptT Source: https://github.com/haskell/mtl/blob/master/README.markdown This example demonstrates lifting an `IO a` action into an `ExceptT MyError IO a` computation. It uses `getLine` to read input and `throwError` to signal an `EmptyLine` error if the input is null. ```haskell data MyError = EmptyLine mightFail :: ExceptT MyError IO () mightFail = do l <- lift getLine when (null l) (throwError EmptyLine) ``` -------------------------------- ### Running Pure Accum Monad Example Source: https://context7.com/haskell/mtl/llms.txt Executes a `MonadAccum` computation within the pure `Accum` monad using `runAccum`, returning the final results and the accumulated log. ```haskell -- Using the pure Accum monad example :: IO () example = do let (results, finalLog) = runAccum (process [1, 2, 3]) [] print results -- [2, 4, 6] mapM_ putStrLn finalLog -- processing 1 -- log entries so far: 1 -- processing 2 -- log entries so far: 3 -- processing 3 -- log entries so far: 5 ``` -------------------------------- ### MonadState: Mutable state operations Source: https://context7.com/haskell/mtl/llms.txt Use MonadState for computations involving mutable state. The `StateT` transformer is the default; use `Control.Monad.State.Strict` for strictness. Key operations include `get`, `put`, `state`, `modify`, `modify'`, and `gets`. ```haskell import Control.Monad.State.Strict type Stack = [Int] push :: MonadState Stack m => Int -> m () push x = modify (x :) pop :: MonadState Stack m => m (Maybe Int) pop = do s <- get case s of [] -> pure Nothing (x:xs) -> put xs >> pure (Just x) stackOps :: State Stack [Maybe Int] stackOps = do push 1 push 2 push 3 a <- pop -- Just 3 b <- pop -- Just 2 push 99 c <- pop -- Just 99 pure [a, b, c] main :: IO () main = do -- runState returns (result, finalState) let (results, finalStack) = runState stackOps [] print results -- [Just 3, Just 2, Just 99] print finalStack -- [1] -- execState discards the result, returns final state print $ execState (push 10 >> push 20) [] -- [20,10] -- evalState discards the final state, returns result print $ evalState (gets length) [1, 2, 3] -- 3 ``` -------------------------------- ### Running RWST Computation Source: https://context7.com/haskell/mtl/llms.txt Demonstrates how to run an `RWST` computation using `runRWST`, `execRWST`, and `evalRWST`, showing how to access the result, final state, and accumulated log. ```haskell runComputation :: IO () runComputation = do let env = Env { multiplier = 3 } initS = State { counter = 5 } -- runRWST returns (result, finalState, accumulatedLog) (result, finalState, logs) <- runRWST compute env initS putStrLn $ "Result: " <> show result -- 15 putStrLn $ "Final state: " <> show finalState -- State {counter = 6} mapM_ putStrLn logs -- step: counter=5, mult=3 -- result: 15 -- execRWST discards the result; evalRWST discards the final state (finalState2, _) <- execRWST (replicateM_ 3 compute) env initS print finalState2 -- State {counter = 8} where replicateM_ n m = mapM_ (const m) [1..n] ``` -------------------------------- ### Select Best Move with MonadSelect Source: https://context7.com/haskell/mtl/llms.txt Demonstrates using MonadSelect to find the best move based on a scoring function. Requires importing Control.Monad.Select and Control.Monad.Trans.Select. ```haskell import Control.Monad.Select import Control.Monad.Trans.Select (runSelect, Select) -- Select the element that maximises a given scoring function bestMove :: Select Int String bestMove = select $ \rank -> -- rank :: String -> Int; pick the string with the highest rank maximumBy (\a b -> compare (rank a) (rank b)) ["cooperate", "defect", "negotiate"] where maximumBy _ [] = error "empty" maximumBy cmp (x:xs) = foldr (\a b -> if cmp a b == GT then a else b) x xs -- Run with a scoring function that prefers "negotiate" main :: IO () main = do let score "cooperate" = 3 score "defect" = 1 score "negotiate" = 5 score _ = 0 print $ runSelect bestMove score -- "negotiate" -- Prefer "defect" let score2 "defect" = 10 score2 _ = 0 print $ runSelect bestMove score2 -- "defect" ``` -------------------------------- ### Lifting Actions with lift in App Source: https://context7.com/haskell/mtl/llms.txt Illustrates lifting actions through multiple transformer layers using `lift`. This is essential for mixing base monad computations (like IO) into a transformer stack. Requires importing Control.Monad.Except, Control.Monad.State.Strict, and Control.Monad.Trans.Class. ```haskell import Control.Monad.Except import Control.Monad.State.Strict import Control.Monad.Trans.Class (lift) data Err = IOFailed String | ParseFailed String deriving (Show) -- StateT Int (ExceptT Err IO) a type App a = StateT Int (ExceptT Err IO) a readAndParse :: App Int readAndParse = do -- lift once: IO -> ExceptT Err IO -- lift twice: IO -> ExceptT Err IO -> StateT Int (ExceptT Err IO) line <- lift . lift $ getLine case reads line of [(n, "")] -> do modify (+n) pure n _ -> lift $ throwError (ParseFailed $ "Not a number: " <> line) runApp :: App a -> Int -> IO (Either Err (a, Int)) runApp action initialState = runExceptT (runStateT action initialState) main :: IO () main = do -- Simulating with a known value via a pure stack let pureApp :: StateT Int (Except Err) Int pureApp = do modify (+10) n <- gets id when (n > 100) $ lift $ throwError (IOFailed "overflow") pure n print $ runExcept (runStateT pureApp 5) -- Right (15, 15) print $ runExcept (runStateT pureApp 95) -- Left (IOFailed "overflow") ``` -------------------------------- ### Re-entrant Label with MonadCont Source: https://context7.com/haskell/mtl/llms.txt Illustrates the use of `label` to create re-entrant continuation points, enabling goto-style jumps within a `ContT` computation. Requires `Control.Monad.Cont`. ```haskell -- label: create a re-entrant continuation countDown :: ContT () IO () countDown = do (loop, n) <- label 5 lift $ print n when (n > 0) $ loop (n - 1) ``` -------------------------------- ### MonadReader: Read-only environment operations Source: https://context7.com/haskell/mtl/llms.txt Use MonadReader for computations that read from a shared, immutable environment. Program against abstract constraints like MonadReader Config m, and use `ask`, `local`, `reader`, or `asks` for environment access. The `local` function is useful for temporarily overriding parts of the environment for sub-computations. ```haskell import Control.Monad.Reader data Config = Config { dbHost :: String, maxRetries :: Int } deriving (Show) -- Constraint-polymorphic: works with any MonadReader Config fetchUser :: MonadReader Config m => Int -> m String fetchUser uid = do host <- asks dbHost retries <- asks maxRetries -- simulate a lookup pure $ "User " <> show uid <> " from " <> host <> " (retries=" <> show retries <> ")" -- Temporarily override part of the environment fetchUserDev :: MonadReader Config m => Int -> m String fetchUserDev uid = local ( cfg -> cfg { dbHost = "localhost" } ) (fetchUser uid) main :: IO () main = do let cfg = Config { dbHost = "db.prod.example.com", maxRetries = 3 } -- runReader unwraps the pure Reader monad putStrLn $ runReader (fetchUser 42) cfg -- "User 42 from db.prod.example.com (retries=3)" putStrLn $ runReader (fetchUserDev 42) cfg -- "User 42 from localhost (retries=3)" -- runReaderT for transformer stacks (here over IO) result <- runReaderT (do u <- fetchUser 1 u' <- fetchUserDev 1 pure (u, u')) cfg print result ``` -------------------------------- ### Update cabal.project for mtl-2.3.1 Source: https://github.com/haskell/mtl/blob/master/docs/Mtl-2.3.x-Migration.md Add this to your cabal.project file to specify the mtl package source and allow newer versions. ```cabal packages: . source-repository-package type: git location: https://github.com/haskell/mtl tag: v2.3.1 allow-newer: *:mtl ``` -------------------------------- ### Simulate For-Loop Break with MonadCont Source: https://context7.com/haskell/mtl/llms.txt Demonstrates simulating a for-loop with a break mechanism using `callCC` to exit the loop early and return a specific value. Requires `Control.Monad.Cont`. ```haskell -- Simulate a for-loop with a break sumUntilNegative :: [Int] -> Cont r Int sumUntilNegative nums = callCC $ \break' -> do total <- flip execStateT 0 $ forM_ nums $ \n -> if n < 0 then lift $ break' 0 -- break out entirely else modify (+n) pure total where execStateT m s = fmap snd (runStateT m s) forM_ = flip mapM_ ``` -------------------------------- ### Combined Reader/Writer/State Computation Source: https://context7.com/haskell/mtl/llms.txt A computation using `RWST` that simultaneously reads from an environment, modifies state, and writes to a log. Requires `Control.Monad.RWS.CPS`. ```haskell import Control.Monad.RWS.CPS -- CPS variant avoids writer space leaks data Env = Env { multiplier :: Int } type Log = [String] data State = State { counter :: Int } deriving (Show) -- Uses all three capabilities simultaneously compute :: RWST Env Log State IO Int compute = do m <- asks multiplier -- read from environment s <- gets counter -- read state tell ["step: counter=" <> show s <> ", mult=" <> show m] let result = s * m modify (\st -> st { counter = counter st + 1 }) tell ["result: " <> show result] return result ``` -------------------------------- ### Accumulating Output with MonadWriter Source: https://context7.com/haskell/mtl/llms.txt Use MonadWriter for computations that produce output alongside a return value. Prefer `Control.Monad.Writer.CPS` for space-leak-free accumulation. `tell` appends to the output, `listen` captures output, and `pass` transforms it. ```haskell import Control.Monad.Writer.CPS -- space-leak-free CPS variant type Log = [String] validateAge :: Int -> Writer Log (Either String Int) validateAge age = do tell ["Checking age: " <> show age] if age < 0 then do tell ["ERROR: negative age"] pure (Left "Age cannot be negative") else if age > 150 then do tell ["ERROR: implausibly large age"] pure (Left "Age too large") else do tell ["OK"] pure (Right age) -- listen captures the sub-computation's log auditedValidation :: Int -> Writer Log (Either String Int, Log) auditedValidation age = listen (validateAge age) main :: IO () main = do let (result, logs) = runWriter (validateAge 25) print result -- Right 25 mapM_ putStrLn logs -- Checking age: 25 -- OK let (result2, logs2) = runWriter (validateAge (-5)) print result2 -- Left "Age cannot be negative" mapM_ putStrLn logs2 -- execWriter discards the return value print $ execWriter (tell ["a"] >> tell ["b"] >> tell ["c"]) -- ["a","b","c"] -- censor post-processes the accumulated output let (_, censored) = runWriter $ censor (filter (/= "OK")) (validateAge 30) print censored -- ["Checking age: 30"] ``` -------------------------------- ### Accumulating Log Messages with MonadAccum Source: https://context7.com/haskell/mtl/llms.txt Processes a list of integers, accumulating log messages and reading the log's length mid-computation using `MonadAccum`. Requires `Control.Monad.Accum`. ```haskell import Control.Monad.Accum import Control.Monad.Trans.Accum (runAccumT, Accum, runAccum) type Log = [String] -- Accumulate log messages and read them back mid-computation process :: MonadAccum Log m => [Int] -> m [Int] process [] = pure [] process (x:xs) = do add ["processing " <> show x] prevCount <- looks length -- read accumulated log length so far add ["log entries so far: " <> show prevCount] rest <- process xs pure (x * 2 : rest) ``` -------------------------------- ### Exception Handling with MonadError Source: https://context7.com/haskell/mtl/llms.txt Use MonadError for exception handling, providing `throwError` to abort and `catchError` to recover. `liftEither` converts `Either` to `MonadError`, and `tryError` catches errors as `Either`. ```haskell import Control.Monad.Except data AppError = NotFound String | InvalidInput String | DatabaseError String deriving (Show) lookupUser :: MonadError AppError m => Int -> m String lookupUser uid | uid <= 0 = throwError (InvalidInput "User ID must be positive") | uid == 99 = throwError (NotFound $ "No user with id " <> show uid) | otherwise = pure $ "alice-" <> show uid safeDiv :: MonadError AppError m => Int -> Int -> m Int safeDiv _ 0 = throwError (InvalidInput "Division by zero") safeDiv x y = pure (x `div` y) -- tryError turns a throw into a Left pipeline :: ExceptT AppError IO () pipeline = do -- liftEither promotes an Either into ExceptT n <- liftEither (Right 42) -- onError: run cleanup if anything after this fails user <- lookupUser n `onError` lift (putStrLn "Cleanup on failure") lift $ putStrLn $ "Got user: " <> user -- withError modifies the error without changing its type result <- withError ( e -> DatabaseError (show e)) (safeDiv n 0) lift $ print result main :: IO () main = do r1 <- runExceptT (lookupUser 5) print r1 -- Right "alice-5" r2 <- runExceptT (lookupUser 99) print r2 -- Left (NotFound "No user with id 99") -- catchError for local recovery r3 <- runExceptT $ lookupUser 99 `catchError` \(NotFound msg) -> pure ("default-user [" <> msg <> "]") print r3 -- Right "default-user [No user with id 99]" -- modifyError: re-embed a sub-error into a parent error type let sub :: ExceptT String IO Int sub = throwError "low-level failure" r4 <- runExceptT (modifyError DatabaseError sub) print r4 -- Left (DatabaseError "low-level failure") ``` -------------------------------- ### MonadTrans lift function signature Source: https://github.com/haskell/mtl/blob/master/README.markdown The `lift` function from `MonadTrans` is used to lift a monadic action into a transformed monadic action. It requires `Monad m` and `MonadTrans t` constraints. ```haskell lift :: (Monad m, MonadTrans t) => m a -> t m a ``` -------------------------------- ### Early Exit with MonadCont Source: https://context7.com/haskell/mtl/llms.txt Use `callCC` to implement early exit from a computation once a condition is met, skipping subsequent operations. Requires `Control.Monad.Cont`. ```haskell import Control.Monad.Cont -- Early exit: once the answer is found, skip remaining computation findFirst :: [Int] -> (Int -> Bool) -> Cont r (Maybe Int) findFirst xs p = callCC $ \exit -> do mapM_ (\x -> when (p x) (exit (Just x))) xs pure Nothing ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.