### Eff Monad: Computation with Reader and State Effects in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates a Haskell computation using the `Eff` monad, combining `Reader` for environment access and `State` for mutable state. It shows how to use `ask`, `gets`, `modify`, and `get` within the `Eff` context and how to run such computations with handlers like `runState` and `runReader`. ```haskell #{-# LANGUAGE DataKinds #-} #{-# LANGUAGE FlexibleContexts #-} #{-# LANGUAGE TypeOperators #-} import Control.Monad.Freer import Control.Monad.Freer.Reader import Control.Monad.Freer.State -- A computation that reads from environment and updates state computation :: Members '[Reader String, State Int] effs => Eff effs Int computation = do name <- ask -- Read from environment len <- gets length -- Get derived value from state (hypothetical) modify (+1) -- Modify state currentState <- get -- Get current state pure currentState -- Run the computation with handlers example :: (Int, Int) example = run $ runState 0 $ runReader "hello" computation -- Result: (1, 1) ``` -------------------------------- ### State Effect Operations (get, put, modify, gets) in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Illustrates the core operations of the State effect: 'put' to set state, 'modify' to update state, 'get' to retrieve current state, and 'gets' to retrieve a derived value from state. This example requires the 'freer' package. ```haskell import Control.Monad.Freer import Control.Monad.Freer.State -- Counter example using State effect counter :: Member (State Int) effs => Eff effs Int counter = do put 0 -- Set initial state modify (+1) -- Increment modify (+1) -- Increment again current <- get -- Get current value doubled <- gets (*2) -- Get derived value pure doubled -- Run with different handlers runStateExample :: (Int, Int) runStateExample = run $ runState 0 counter -- Result: (4, 2) execStateExample :: Int execStateExample = run $ execState 0 counter -- Result: 2 (final state only) evalStateExample :: Int evalStateExample = run $ evalState 0 counter -- Result: 4 (return value only) ``` -------------------------------- ### Run and RunM: Extracting Results from Eff Computations in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Explains and demonstrates the use of `run` and `runM` functions in Haskell's `freer-simple` library. `run` is used to extract results from pure `Eff` computations, while `runM` is for computations with a single remaining monadic effect, such as `IO`. ```haskell import Control.Monad.Freer import Control.Monad.Freer.State import Control.Monad.Freer.Reader -- Pure computation - use run pureExample :: Int pureExample = run $ runState 0 $ do modify (+10) get -- Result: 10 -- IO computation - use runM ioExample :: IO () ioExample = runM $ do sendM $ putStrLn "Hello from Eff!" sendM $ putStrLn "Using IO as the base monad" -- Output: -- Hello from Eff! -- Using IO as the base monad ``` -------------------------------- ### Interpret Console Effects Purely with State and Writer Source: https://github.com/lexi-lambda/freer-simple/blob/master/README.md Implements a pure interpreter for the 'Console' effect using 'State' for input/output simulation and 'Writer' for capturing output. 'runConsolePure' takes a list of input strings and returns the captured output strings, simulating console interactions without actual IO. It also handles errors and state management. ```haskell -------------------------------------------------------------------------------- -- Pure Interpreter -- -------------------------------------------------------------------------------- runConsolePure :: [String] -> Eff '[Console] w -> [String] runConsolePure inputs req = snd . fst $ run (runWriter (runState inputs (runError (reinterpret3 go req)))) where go :: Console v -> Eff '[Error (), State [String], Writer [String]] v go (PutStrLn msg) = tell [msg] go GetLine = get >>= \case [] -> error "not enough lines" (x:xs) -> put xs >> pure x go ExitSuccess = throwError () ``` -------------------------------- ### Send: Lifting Custom Effects into Eff Monad in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Illustrates how to define custom effects (e.g., `FileSystem`) and lift them into the `Eff` monad using the `send` function in Haskell. It defines effect operations like `readFile'` and `writeFile'` and shows their usage within a computation like `copyFile`. ```haskell #{-# LANGUAGE GADTs #-} #{-# LANGUAGE FlexibleContexts #-} import Control.Monad.Freer -- Define a custom effect data FileSystem r where ReadFile :: FilePath -> FileSystem String WriteFile :: FilePath -> String -> FileSystem () -- Create operations using send readFile' :: Member FileSystem effs => FilePath -> Eff effs String readFile' path = send (ReadFile path) writeFile' :: Member FileSystem effs => FilePath -> String -> Eff effs () writeFile' path contents = send (WriteFile path contents) -- Usage in a computation copyFile :: Member FileSystem effs => FilePath -> FilePath -> Eff effs () copyFile src dst = do contents <- readFile' src writeFile' dst contents ``` -------------------------------- ### Custom Effect with Pure and IO Interpreters (Haskell) Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Defines a Console effect with both a pure, testable interpreter and an effectful IO interpreter. This demonstrates how to create and run custom effects for different environments, facilitating testing and production use. ```haskell #{-# LANGUAGE GADTs #-} #{-# LANGUAGE LambdaCase #-} #{-# LANGUAGE TypeOperators #-} import Control.Monad.Freer import Control.Monad.Freer.Error import Control.Monad.Freer.State import Control.Monad.Freer.Writer -- Define a Console effect data Console r where PutStrLn :: String -> Console () GetLine :: Console String ExitSuccess :: Console () putStrLn' :: Member Console effs => String -> Eff effs () putStrLn' = send . PutStrLn getLine' :: Member Console effs => Eff effs String getLine' = send GetLine exitSuccess' :: Member Console effs => Eff effs () exitSuccess' = send ExitSuccess -- Production interpreter using IO runConsoleIO :: LastMember IO effs => Eff (Console ': effs) a -> Eff effs a runConsoleIO = interpretM $ \case PutStrLn msg -> putStrLn msg GetLine -> getLine ExitSuccess -> error "exit" -- simplified -- Pure interpreter for testing runConsolePure :: [String] -> Eff '[Console] a -> [String] runConsolePure inputs req = snd . fst $ run (runWriter (runState inputs (runError (reinterpret3 go req)))) where go :: Console v -> Eff '[Error (), State [String], Writer [String]] v go (PutStrLn msg) = tell [msg] go GetLine = get >>= \case [] -> error "no more input" (x:xs) -> put xs >> pure x go ExitSuccess = throwError () -- Test program echoProgram :: Member Console effs => Eff effs () echoProgram = do putStrLn' "Enter your name:" name <- getLine' putStrLn' $ "Hello, " ++ name ++ "!" -- Pure test testOutput :: [String] testOutput = runConsolePure ["Alice"] echoProgram -- Result: ["Enter your name:", "Hello, Alice!"] ``` -------------------------------- ### Reinterpret KeyValue Effect using State in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates how to reinterpret the 'KeyValue' effect into the 'State' effect using the 'reinterpret' function. This allows implementing one effect in terms of another. It requires the 'containers' package for 'Data.Map'. ```haskell {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TypeOperators #-} import Control.Monad.Freer import Control.Monad.Freer.State import qualified Data.Map as Map data KeyValue k v r where Lookup :: k -> KeyValue k v (Maybe v) Insert :: k -> v -> KeyValue k v () lookup' :: Member (KeyValue k v) effs => k -> Eff effs (Maybe v) lookup' = send . Lookup insert' :: Member (KeyValue k v) effs => k -> v -> Eff effs () insert' k v = send (Insert k v) -- Reinterpret KeyValue in terms of State runKeyValue :: Ord k => Eff (KeyValue k v ': effs) a -> Eff (State (Map.Map k v) ': effs) a runKeyValue = reinterpret $ \case Lookup k -> gets (Map.lookup k) Insert k v -> modify (Map.insert k v) -- Full example kvExample :: Int kvExample = run $ evalState Map.empty $ runKeyValue $ do insert' "x" 10 insert' "y" 20 mx <- lookup' "x" pure $ maybe 0 id mx -- Result: 10 ``` -------------------------------- ### Interpret: Handling Effects with Natural Transformations in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Shows how to use the `interpret` function in Haskell's `freer-simple` library to handle effects. It defines a `Teletype` effect and demonstrates how to provide an `IO`-based interpreter using `interpretM` for reading from and writing to the console. ```haskell #{-# LANGUAGE GADTs #-} #{-# LANGUAGE LambdaCase #-} import Control.Monad.Freer data Teletype r where ReadTTY :: Teletype String WriteTTY :: String -> Teletype () readTTY :: Member Teletype effs => Eff effs String readTTY = send ReadTTY writeTTY :: Member Teletype effs => String -> Eff effs () writeTTY = send . WriteTTY -- Handle Teletype using IO runTeletype :: LastMember IO effs => Eff (Teletype ': effs) a -> Eff effs a runTeletype = interpretM $ \case ReadTTY -> getLine WriteTTY msg -> putStrLn msg -- Example program program :: Member Teletype effs => Eff effs () program = do writeTTY "What is your name?" name <- readTTY writeTTY $ "Hello, " ++ name ++ "!" -- Run with IO main :: IO () main = runM $ runTeletype program ``` -------------------------------- ### Reader Effect Operations (ask, asks, local) in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Explains the Reader effect for accessing an immutable environment. 'ask' retrieves the entire environment, 'asks' retrieves a part of it, and 'local' temporarily modifies the environment for a subcomputation. Requires 'freer' and 'containers' packages. ```haskell import Control.Monad.Freer import Control.Monad.Freer.Reader import qualified Data.Map as Map type Config = Map.Map String String -- Reading configuration getConfigValue :: Member (Reader Config) effs => String -> Eff effs (Maybe String) getConfigValue key = asks (Map.lookup key) -- Using local to temporarily modify the environment withPrefix :: Member (Reader Config) effs => String -> Eff effs a -> Eff effs a withPrefix prefix = local (Map.mapKeys (prefix ++)) -- Complete example configExample :: (Maybe String, Maybe String) configExample = run $ runReader config $ do dbHost <- getConfigValue "db.host" -- Temporarily modify keys with prefix prefixedHost <- withPrefix "prod." $ getConfigValue "db.host" pure (dbHost, prefixedHost) where config = Map.fromList [ ("db.host", "localhost") , ("prod.db.host", "production.db.example.com") ] -- Result: (Just "localhost", Just "production.db.example.com") ``` -------------------------------- ### Interpret Console Effects with IO Source: https://github.com/lexi-lambda/freer-simple/blob/master/README.md Provides an IO-based interpreter for the 'Console' effect, integrating it with the base 'IO' monad. The 'runConsole' function translates 'Console' operations into their corresponding 'IO' actions like 'Prelude.putStrLn', 'Prelude.getLine', and 'System.Exit.exitSuccess'. ```haskell -------------------------------------------------------------------------------- -- Effectful Interpreter -- -------------------------------------------------------------------------------- runConsole :: Eff '[Console, IO] a -> IO a runConsole = runM . interpretM (case PutStrLn msg -> Prelude.putStrLn msg GetLine -> Prelude.getLine ExitSuccess -> System.Exit.exitSuccess) ``` -------------------------------- ### Debugging with Trace Effect Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Shows how to use the Trace effect for debugging purposes. The `trace` function logs messages to the console during computation. `runTrace` executes the traced computation and returns its result, while also printing the trace messages. ```haskell import Control.Monad.Freer import Control.Monad.Freer.Trace import Control.Monad.Freer.Reader -- Traced computation tracedSum :: Member Trace effs => [Int] -> Eff effs Int tracedSum [] = do trace "Reached empty list, returning 0" pure 0 tracedSum (x:xs) = do trace $ "Processing element: " ++ show x rest <- tracedSum xs trace $ "Sum so far: " ++ show (x + rest) pure (x + rest) -- Run with trace output traceExample :: IO Int traceExample = runTrace $ tracedSum [1, 2, 3] -- Output: -- Processing element: 1 -- Processing element: 2 -- Processing element: 3 -- Reached empty list, returning 0 -- Sum so far: 3 -- Sum so far: 5 -- Sum so far: 6 -- Result: 6 ``` -------------------------------- ### Error Handling with Freer-Simple Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates exception handling using the Error effect in freer-simple. It shows how to define custom errors, throw them using `throwError`, catch them with `catchError`, and run computations that may fail using `runError`. ```haskell import Control.Monad.Freer import Control.Monad.Freer.Error data AppError = NotFound String | InvalidInput String deriving Show -- Computation that may fail findUser :: Member (Error AppError) effs => String -> Eff effs String findUser userId = if userId == "admin" then pure "Administrator" else throwError (NotFound $ "User " ++ userId ++ " not found") -- With error recovery findUserSafe :: Member (Error AppError) effs => String -> Eff effs String findUserSafe userId = findUser userId `catchError` \case NotFound _ -> pure "Guest" other -> throwError other -- Run examples errorExample1 :: Either AppError String errorExample1 = run $ runError $ findUser "admin" -- Result: Right "Administrator" errorExample2 :: Either AppError String errorExample2 = run $ runError $ findUser "unknown" -- Result: Left (NotFound "User unknown not found") errorExample3 :: Either AppError String errorExample3 = run $ runError $ findUserSafe "unknown" -- Result: Right "Guest" ``` -------------------------------- ### Writer Effect Operations (tell, runWriter) in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates the Writer effect for accumulating output values, such as logs or messages. 'tell' appends a value to the log, and 'runWriter' executes the computation and returns the final result along with the accumulated log. Requires the 'freer' package. ```haskell import Control.Monad.Freer import Control.Monad.Freer.Writer -- Logging computation steps factorial :: Member (Writer [String]) effs => Int -> Eff effs Int factorial n = do tell ["Computing factorial of " ++ show n] if n <= 1 then do tell ["Base case reached"] pure 1 else do tell ["Recursing with " ++ show (n-1)] rest <- factorial (n - 1) pure (n * rest) -- Run and collect logs writerExample :: (Int, [String]) writerExample = run $ runWriter $ factorial 4 -- Result: (24, ["Computing factorial of 4", -- "Recursing with 3", -- "Computing factorial of 3", -- "Recursing with 2", -- "Computing factorial of 2", -- "Recursing with 1", -- "Computing factorial of 1", -- "Base case reached"]) ``` -------------------------------- ### Transactional State with Rollback in Haskell Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates 'transactionState' for providing transactional semantics to state updates. If a transaction fails (e.g., due to an 'Error' effect), the state changes are rolled back. Requires 'freer' and 'mtl' packages. ```haskell {-# LANGUAGE TypeApplications #-} import Control.Monad.Freer import Control.Monad.Freer.State import Control.Monad.Freer.Error -- Transaction that might fail riskyOperation :: Members '[State Int, Error String] effs => Eff effs () riskyOperation = transactionState @Int $ do modify (+100) current <- get if current > 50 then throwError "Value too high!" else pure () -- The state rollback on error transactionExample :: Either String ((), Int) transactionExample = run $ runError $ runState 0 riskyOperation -- Result: Left "Value too high!" -- State remains 0 due to transaction rollback ``` -------------------------------- ### Unique ID Generation with Fresh Effect Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Illustrates the use of the Fresh effect for generating unique integer identifiers. The `fresh` function produces a new integer each time it's called, and `evalFresh` initializes the counter. This is useful for creating distinct entities. ```haskell import Control.Monad.Freer import Control.Monad.Freer.Fresh -- Generate unique identifiers data Entity = Entity { entityId :: Int, entityName :: String } deriving Show createEntity :: Member Fresh effs => String -> Eff effs Entity createEntity name = do eid <- fresh pure $ Entity eid name -- Create multiple entities with unique IDs createEntities :: Member Fresh effs => [String] -> Eff effs [Entity] createEntities = mapM createEntity -- Run example freshExample :: [Entity] freshExample = run $ evalFresh 1 $ createEntities ["Alice", "Bob", "Charlie"] -- Result: [Entity {entityId = 1, entityName = "Alice"}, -- Entity {entityId = 2, entityName = "Bob"}, -- Entity {entityId = 3, entityName = "Charlie"}] ``` -------------------------------- ### Non-Deterministic Computations with NonDet Effect Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Demonstrates the NonDet effect for handling computations with multiple possible outcomes. `choose` selects an element non-deterministically from a list, and `empty` represents a failed branch. `makeChoiceA` collects all possible results. ```haskell import Control.Monad.Freer import Control.Monad.Freer.NonDet import Control.Applicative ((<|>), empty) -- Non-deterministic choice choose :: Member NonDet effs => [a] -> Eff effs a choose = foldr ((<|>) . pure) empty -- Find all Pythagorean triples up to n pythagoreanTriples :: Member NonDet effs => Int -> Eff effs (Int, Int, Int) pythagoreanTriples n = do a <- choose [1..n] b <- choose [a..n] c <- choose [b..n] if a*a + b*b == c*c then pure (a, b, c) else empty -- Collect all results nonDetExample :: [(Int, Int, Int)] nonDetExample = run $ makeChoiceA $ pythagoreanTriples 20 -- Result: [(3,4,5),(5,12,13),(6,8,10),(8,15,17),(9,12,15),(12,16,20)] ``` -------------------------------- ### Generate Database Effect Operations with makeEffect (Haskell) Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Automatically generates effect operations (query, insert, delete) from a GADT definition using Template Haskell. This simplifies the creation of effectful functions, making them ready for use within the Eff monad. ```haskell #{-# LANGUAGE GADTs #-} #{-# LANGUAGE TemplateHaskell #-} #{-# LANGUAGE FlexibleContexts #-} import Control.Monad.Freer import Control.Monad.Freer.TH -- Define effect algebra data Database r where Query :: String -> Database [String] Insert :: String -> Database Bool Delete :: Int -> Database Bool -- Generate operations automatically -- This creates: query, insert, delete functions makeEffect ''Database -- Now you can use the generated functions: -- query :: Member Database effs => String -> Eff effs [String] -- insert :: Member Database effs => String -> Eff effs Bool -- delete :: Member Database effs => Int -> Eff effs Bool -- Example usage dbProgram :: Member Database effs => Eff effs [String] dbProgram = do _ <- insert "new record" results <- query "SELECT * FROM table" _ <- delete 1 pure results ``` -------------------------------- ### Suspendable Computations with Coroutine Effect Source: https://context7.com/lexi-lambda/freer-simple/llms.txt Explains the Coroutine (Yield) effect for creating suspendable computations. The `yield` function pauses execution and returns a value, allowing for generators. `runC` runs the coroutine, and `processCoroutine` demonstrates how to handle the yielded values and the continuation. ```haskell {-# LANGUAGE TypeOperators #-} import Control.Monad.Freer import Control.Monad.Freer.Coroutine -- A generator that yields integers generator :: Member (Yield Int ()) effs => Eff effs String generator = do yield 1 id yield 2 id yield 3 id pure "Done!" -- Process yielded values processCoroutine :: Eff effs (Status effs Int () a) -> Eff effs [Int] processCoroutine m = do status <- m case status of Done _ -> pure [] Continue x k -> do rest <- processCoroutine (k ()) pure (x : rest) -- Run the generator coroutineExample :: [Int] coroutineExample = run $ processCoroutine $ runC generator -- Result: [1, 2, 3] ``` -------------------------------- ### Define Console Effects with freer-simple Source: https://github.com/lexi-lambda/freer-simple/blob/master/README.md Defines a 'Console' effect with operations for 'PutStrLn', 'GetLine', and 'ExitSuccess' using the freer-simple library's 'makeEffect' TH. This allows these console interactions to be treated as effects within the Haskell type system. ```haskell {-# LANGUAGE DataKinds #} {-# LANGUAGE FlexibleContexts #} {-# LANGUAGE GADTs #} {-# LANGUAGE LambdaCase #} {-# LANGUAGE TemplateHaskell #} {-# LANGUAGE TypeOperators #} import qualified Prelude import qualified System.Exit import Prelude hiding (putStrLn, getLine) import Control.Monad.Freer import Control.Monad.Freer.TH import Control.Monad.Freer.Error import Control.Monad.Freer.State import Control.Moner.Freer.Writer -------------------------------------------------------------------------------- -- Effect Model -- -------------------------------------------------------------------------------- data Console r where PutStrLn :: String -> Console () GetLine :: Console String ExitSuccess :: Console () makeEffect ''Console ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.