### Install Dunai using Cabal Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Installs the Dunai library using the Cabal build tool. This command updates the package list and then installs the library. Ensure you have GHC and cabal-install installed. ```bash cabal update cabal install --lib dunai ``` -------------------------------- ### Verify Dunai Installation Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Verifies the successful installation of the Dunai library by importing a module and printing 'Success'. This script requires a working Haskell environment and the Dunai library to be installed. ```haskell import Data.MonadicStreamFunction main = putStrLn "Success" ``` -------------------------------- ### Verify Dunai Installation Source: https://github.com/ivanperez-keera/dunai/blob/develop/dunai/README.md Verifies the successful installation of Dunai by running a simple Haskell program that imports a module from the library and prints 'Success'. This confirms that the library is accessible and functional. ```bash runhaskell <<< 'import Data.MonadicStreamFunction; main = putStrLn "Success"' ``` -------------------------------- ### Alternative Syntax for Piping MSFs with Applicative Style Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Presents an alternative way to write the `reactimate` example using applicative style (`<$>`) combined with function composition (`.`) for a more concise expression. ```haskell ghci> reactimate (arrM putStrLn . (reverse <$> constM getLine)) Hello olleH Haskell is awesome emosewa si lleksaH ^C ``` -------------------------------- ### Install GHC and Cabal on Debian/Ubuntu Source: https://github.com/ivanperez-keera/dunai/blob/develop/dunai/README.md Installs the Glasgow Haskell Compiler (GHC) and Cabal build tool on Debian or Ubuntu systems using the apt-get package manager. These are prerequisites for compiling and installing Haskell libraries like Dunai. ```bash apt-get install ghc cabal-install ``` -------------------------------- ### Install GHC and Cabal on macOS Source: https://github.com/ivanperez-keera/dunai/blob/develop/dunai/README.md Installs the Glasgow Haskell Compiler (GHC) and Cabal build tool on macOS using the Homebrew package manager. These are prerequisites for compiling and installing Haskell libraries like Dunai. ```bash brew install ghc cabal-install ``` -------------------------------- ### Equivalent MSF Piping using fmap Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Shows another equivalent syntax for the `reactimate` example, explicitly using `fmap` (which is equivalent to `<$>`) for transforming the output of `constM getLine` before piping it. ```haskell ghci> reactimate (arrM putStrLn . fmap reverse . constM getLine) Hello olleH Haskell is awesome emosewa si lleksaH ^C ``` -------------------------------- ### Install and Run Haskanoid with Dunai/Bearriver Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md This snippet demonstrates how to clone the Haskanoid game, install its dependencies including Dunai/Bearriver with specific flags, and then run the game. It highlights the performance of the game using unaccelerated SDL 1.2. ```shell git clone https://github.com/ivanperez-keera/haskanoid.git cd haskanoid/ cabal install -f-wiimote -f-kinect -fbearriver $ haskanoid ``` -------------------------------- ### Simulation with reactimate in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Introduces the `reactimate` function for running an MSF indefinitely, suitable for continuous simulations. An example demonstrates an interactive string reverser using `constM` and `arrM`. ```haskell import Data.MonadicStreamFunction import Control.Monad (void) -- Interactive string reverser reverseEcho :: MSF IO () () reverseEcho = constM getLine >>> arr reverse >>> arrM putStrLn main :: IO () main = reactimate reverseEcho -- User types: Hello -- Output: olleH -- User types: Haskell -- Output: lleksaH -- (continues until Ctrl+C) ``` -------------------------------- ### Run Indefinite MSF Simulation with reactimate Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Uses `reactimate` to run an MSF simulation indefinitely. This example pipes input from `getLine` (via `constM`), reverses it, and prints it using `arrM putStrLn`. ```haskell ghci> reactimate (constM getLine >>> arr reverse >>> arrM putStrLn) Hello olleH Haskell is awesome emosewa si lleksaH ^C ``` -------------------------------- ### Integrate Reader Monad with MSFs (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt This section covers integrating the Reader monad with Monadic Stream Functions (MSFs) using `readerS` and `runReaderS_` from `Control.Monad.Trans.MSF.Reader`. It demonstrates how an MSF can access an environment (configuration) for its computations. The example shows an MSF that multiplies its input by a multiplier read from the environment. ```haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.Reader -- MSF that reads from environment type Config = Int -- multiplier configuredMSF :: MSF (ReaderT Config IO) Int Int configuredMSF = arrM $ \x -> do multiplier <- ask return (x * multiplier) -- Run with fixed environment main :: IO () main = do let msf = runReaderS_ configuredMSF 10 result <- embed msf [1, 2, 3, 4, 5] print result -- Output: [10, 20, 30, 40, 50] ``` -------------------------------- ### Constant Monadic Streams with constM in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Illustrates the use of `constM` to create an MSF that repeatedly executes a monadic action, ignoring its input. Examples include reading lines from stdin and echoing user input. ```haskell import Data.MonadicStreamFunction import Control.Monad (void) -- Create stream that reads lines from stdin getLineMSF :: MSF IO a String getLineMSF = constM getLine -- Echo user input back echoProgram :: MSF IO () () echoProgram = constM getLine >>> arrM putStrLn -- Run indefinitely (Ctrl+C to stop) main :: IO () main = reactimate echoProgram -- User types: Hello -- Output: Hello -- User types: World -- Output: World ``` -------------------------------- ### Create Stateful Loops with feedback (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt The `feedback` combinator in `Data.MonadicStreamFunction` is used to create well-formed feedback loops. It connects an output component as a future input, enabling stateful computations and accumulation patterns. This is demonstrated with `runningSum` and `counter` examples. ```haskell import Data.MonadicStreamFunction -- Accumulate sum using feedback runningSum :: (Num a, Monad m) => MSF m a a runningSum = feedback 0 $ arr ((input, acc) -> let newAcc = input + acc in (newAcc, newAcc)) -- Counter using feedback counter :: (Num a, Monad m) => MSF m () a counter = feedback 0 $ arr (((), n) -> (n + 1, n + 1)) main :: IO () main = do sums <- embed runningSum [1, 2, 3, 4, 5] print sums -- Output: [1, 3, 6, 10, 15] counts <- embed counter [(), (), (), (), ()] print counts -- Output: [1, 2, 3, 4, 5] ``` -------------------------------- ### Applicative and Functor Style MSFs (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt Illustrates how Monadic Stream Functions (MSFs) in Dunai can be used with Applicative and Functor instances for functional-style transformations. Examples include combining MSFs with `liftA2`, mapping functions with `fmap` (or `<$>`), and using `pure` to create constant MSFs. Dependencies include Data.MonadicStreamFunction and Control.Applicative. ```Haskell import Data.MonadicStreamFunction import Control.Applicative (liftA2) -- Applicative combination of MSFs combinedMSF :: Monad m => MSF m Int Int combinedMSF = liftA2 (+) (arr (*2)) (arr (*3)) -- Equivalent to: \x -> (x*2) + (x*3) = x*5 -- Functor mapping mappedMSF :: Monad m => MSF m Int String mappedMSF = show <$> arr (*2) -- Pure values in MSF context constantMSF :: Monad m => MSF m a Int constantMSF = pure 42 main :: IO () main = do result1 <- embed combinedMSF [1, 2, 3, 4, 5] print result1 -- Output: [5, 10, 15, 20, 25] result2 <- embed mappedMSF [1, 2, 3] print result2 -- Output: ["2", "4", "6"] result3 <- embed constantMSF [(), (), ()] print result3 -- Output: [42, 42, 42] ``` -------------------------------- ### Delay Signals with iPre (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt The `iPre` function from `Data.MonadicStreamFunction` delays a signal by one sample, outputting a given initial value first. It is essential for creating well-defined feedback loops where the previous state is needed. Examples include a simple delay and a differentiator. ```haskell import Data.MonadicStreamFunction -- Delay signal by one step delayedMSF :: Monad m => MSF m Int Int delayedMSF = iPre 0 -- Compute difference between current and previous value differentiator :: (Num a, Monad m) => MSF m a a differentiator = (arr id &&& iPre 0) >>> arr (uncurry (-)) main :: IO () main = do delayed <- embed (iPre 0) [1, 2, 3, 4, 5] print delayed -- Output: [0, 1, 2, 3, 4] diffs <- embed differentiator [1, 3, 6, 10, 15] print diffs -- Output: [1, 2, 3, 4, 5] ``` -------------------------------- ### Integrate State Monad with MSFs (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt This snippet illustrates integrating the State monad with Monadic Stream Functions (MSFs) using `stateS` and `runStateS_` from `Control.Monad.Trans.MSF.State`. It shows how an MSF can maintain and modify internal mutable state. The example defines a stateful MSF that accumulates its inputs and returns the state before the update. ```haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.State -- MSF that maintains state statefulMSF :: MSF (StateT Int IO) Int Int statefulMSF = arrM $ \input -> do current <- get put (current + input) return current -- Run and observe state changes main :: IO () main = do -- runStateS_ returns (state, output) pairs let msf = runStateS_ statefulMSF 0 result <- embed msf [1, 2, 3, 4, 5] print result -- Output: [(1,0), (3,1), (6,3), (10,6), (15,10)] -- Each tuple is (newState, outputBeforeUpdate) ``` -------------------------------- ### Lift MSFs Across Monads with morphS and morphGS (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt The `morphS` and `morphGS` functions from `Data.MonadicStreamFunction` allow lifting Monadic Stream Functions (MSFs) across different monads. `morphS` applies a natural transformation, while `morphGS` offers more general lifting capabilities. An example shows how to convert a pure `Identity` MSF to an `IO` MSF. ```haskell import Data.MonadicStreamFunction import Data.Functor.Identity -- Convert pure MSF to IO MSF pureToIO :: MSF Identity a b -> MSF IO a b pureToIO = morphS (return . runIdentity) -- Example: lift a pure computation into IO pureMSF :: MSF Identity Int Int pureMSF = arr (*2) ioMSF :: MSF IO Int Int ioMSF = pureToIO pureMSF main :: IO () main = do result <- embed ioMSF [1, 2, 3, 4, 5] print result -- Output: [2, 4, 6, 8, 10] ``` -------------------------------- ### Accumulate Values with accumulateWith and mealy (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt This snippet demonstrates accumulation patterns using `accumulateWith` and `mealy` from `Data.MonadicStreamFunction`. `accumulateWith` applies a folding function to inputs and an accumulator, while `mealy` implements general Mealy machines for state transitions and output generation. Examples include counting inputs, calculating running products, and finding running maximums. ```haskell import Data.MonadicStreamFunction -- Count number of inputs countMSF :: (Num n, Monad m) => MSF m a n countMSF = arr (const 1) >>> accumulateWith (+) 0 -- Mealy machine: output running product, state is product so far runningProduct :: (Num a, Monad m) => MSF m a a runningProduct = mealy (a s -> (a * s, a * s)) 1 -- Accumulate with custom function customAccum :: Monad m => MSF m Int Int customAccum = accumulateWith max 0 -- Running maximum main :: IO () main = do counts <- embed countMSF ["a", "b", "c", "d"] print counts -- Output: [1, 2, 3, 4] products <- embed runningProduct [1, 2, 3, 4, 5] print products -- Output: [1, 2, 6, 24, 120] maxes <- embed customAccum [3, 1, 4, 1, 5, 9, 2, 6] print maxes -- Output: [3, 3, 4, 4, 5, 9, 9, 9] ``` -------------------------------- ### Core MSF Type and Construction in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Demonstrates the fundamental MSF type and how to construct a simple incrementing MSF using `arr`. It also shows how to run an MSF with a list of inputs using `embed`. ```haskell import Data.MonadicStreamFunction -- The core MSF type definition -- data MSF m a b = MSF { unMSF :: a -> m (b, MSF m a b) } -- Create MSF from pure function using arr incrementMSF :: Monad m => MSF m Int Int incrementMSF = arr (+1) -- Run MSF with a list of inputs main :: IO () main = do result <- embed incrementMSF [1, 2, 3, 4, 5] print result -- Output: [2, 3, 4, 5, 6] ``` -------------------------------- ### Debugging MSFs with trace and traceWith in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Explains how to use `trace` and `traceWith` for debugging MSFs by outputting each sample's value. These functions pass the values through unchanged, making them suitable for insertion into existing pipelines without altering their behavior. ```haskell import Data.MonadicStreamFunction import Control.Monad (void) -- Trace with prefix debugMSF :: MSF IO Int Int debugMSF = trace "Value: " -- Custom trace with condition conditionalTrace :: MSF IO Int Int conditionalTrace = traceWhen (> 5) putStrLn "Large value: " -- Trace in pipeline tracedPipeline :: MSF IO Int Int tracedPipeline = arr (*2) >>> trace "After *2: " >>> arr (+1) >>> trace "After +1: " main :: IO () main = do putStrLn "=== Basic trace ===" void $ embed debugMSF [1, 2, 3] -- Output: -- Value: 1 -- Value: 2 -- Value: 3 putStrLn "\n=== Traced pipeline ===" void $ embed tracedPipeline [1, 2, 3] -- Output: -- After *2: 2 -- After +1: 3 -- After *2: 4 -- After +1: 5 -- After *2: 6 -- After +1: 7 ``` -------------------------------- ### Convert Pure Function to MSF and Embed Inputs Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Demonstrates converting a pure function (adding 1) into an MSF using `arr` and then running this MSF with a list of inputs using `embed` to collect outputs. ```haskell ghci> embed (arr (+1)) [1,2,3,4,5] [2,3,4,5,6] ``` -------------------------------- ### Combine Input Reading and Output Printing MSFs Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Combines `constM getLine` (to read input) and `arrM putStrLn` (to print output) using `>>>`. The `embed` function runs this combined MSF twice, demonstrating interactive input/output. ```haskell ghci> void $ embed (constM getLine >>> arrM putStrLn) [(), ()] What the user types, the computer repeats. What the user types, the computer repeats. Once again, the computer repeats. Once again, the computer repeats. ``` -------------------------------- ### Pipe MSFs for Sequential Processing Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Demonstrates piping two MSFs together using the `>>>` operator. The output of the first MSF (`arr (+1)`) becomes the input for the second MSF (`arrM print`), processing each element sequentially. ```haskell ghci> void $ embed (arr (+1) >>> arrM print) [1,2,3,4,5] 2 3 4 5 6 ``` -------------------------------- ### Optional Outputs with MaybeT in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Illustrates how to create MSFs that can exit or produce no output using the Maybe transformer. Functions like `exitWhen` and `exitIf` are used to control the flow, and `runMaybeS` converts the result to a standard MSF with `Maybe` outputs. ```haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.Maybe -- MSF that exits when input is zero exitOnZero :: MSF (MaybeT IO) Int Int exitOnZero = exitWhen (== 0) -- Run until exit condition untilCondition :: MSF (MaybeT IO) Int Int untilCondition = proc x -> do _ <- exitIf -< x > 10 returnA -< x * 2 -- Convert to regular MSF with Maybe output main :: IO () main = do result1 <- embed (runMaybeS exitOnZero) [1, 2, 3, 0, 4, 5] print result1 -- Output: [Just 1, Just 2, Just 3, Nothing, Just 4, Just 5] result2 <- embed (runMaybeS untilCondition) [1, 5, 10, 15, 20] print result2 -- Output: [Just 2, Just 10, Just 20, Nothing, Nothing] ``` -------------------------------- ### Sequential Composition of MSFs in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Demonstrates sequential composition of MSFs using the `(>>>)` and `(.)` operators from the `Category` typeclass. This chains transformations, where the output of one MSF becomes the input of the next. ```haskell import Data.MonadicStreamFunction import Control.Monad (void) -- Chain transformations: add 1, then multiply by 2, then print pipeline :: MSF IO Int () pipeline = arr (+1) >>> arr (*2) >>> arrM print main :: IO () main = do void $ embed pipeline [1, 2, 3, 4, 5] -- Output: -- 4 -- (1+1)*2 -- 6 -- (2+1)*2 -- 8 -- (3+1)*2 -- 10 -- (4+1)*2 -- 12 -- (5+1)*2 ``` -------------------------------- ### Parallel Composition of MSFs in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Explains and demonstrates parallel composition of MSFs using Arrow combinators `(&&&)` and `(***)`. `(&&&)` applies two MSFs to the same input, while `(***)` applies them to different components of a tuple input. ```haskell import Data.MonadicStreamFunction import Control.Arrow ((&&&), (***)) -- Run two computations in parallel parallelMSF :: Monad m => MSF m Int (Int, Int) parallelMSF = arr (+1) &&& arr (*2) -- Apply different transformations to tuple components tupleMSF :: Monad m => MSF m (Int, String) (Int, Int) tupleMSF = arr (*10) *** arr length main :: IO () main = do result1 <- embed parallelMSF [1, 2, 3] print result1 -- Output: [(2,2), (3,4), (4,6)] result2 <- embed tupleMSF [(1, "hello"), (2, "world"), (3, "!")] print result2 -- Output: [(10,5), (20,5), (30,1)] ``` -------------------------------- ### Haskanoid Performance Report Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md This snippet shows a sample performance report for the Haskanoid game when run with Dunai/Bearriver. It details the time per frame, frames per second (FPS), and total running time, indicating performance metrics for the game. ```text Performance report :: Time per frame: 13.88ms, FPS: 72.04610951008645, Total running time: 1447 Performance report :: Time per frame: 16.46ms, FPS: 60.75334143377886, Total running time: 3093 Performance report :: Time per frame: 17.48ms, FPS: 57.20823798627002, Total running time: 4841 Performance report :: Time per frame: 19.56ms, FPS: 51.12474437627812, Total running time: 6797 Performance report :: Time per frame: 19.96ms, FPS: 50.100200400801604, Total running time: 8793 Performance report :: Time per frame: 19.44ms, FPS: 51.440329218106996, Total running time: 10737 ``` -------------------------------- ### Exception Handling with ExceptT in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Demonstrates exception throwing and catching using the Except transformer for MSFs. It shows how to define MSFs that can throw exceptions (`throwS`) and how to recover from them using `catchS` or handle them sequentially within the `MSFExcept` monad. ```haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.Except -- MSF that throws exception when condition met throwOnNegative :: MSF (ExceptT String IO) Int Int throwOnNegative = proc x -> do if x < 0 then throwS -< "Negative number: " ++ show x else returnA -< x * 2 -- Catch and recover from exceptions safeProcessing :: MSF IO Int Int safeProcessing = catchS throwOnNegative $ \err -> do arrM $ \x -> putStrLn ("Recovered from: " ++ err) >> return x -- Using MSFExcept monad for sequential exception handling sequentialExcept :: MSFExcept IO () () String sequentialExcept = do -- Run first phase try $ arrM (const $ putStrLn "Phase 1") >>> arr (const ()) -- Then throw result once_ $ return "Completed all phases" main :: IO () main = do result <- embed safeProcessing [1, 2, -3, 4, 5] print result -- Output: Recovered from: Negative number: -3 -- [2, 4, -3, 8, 10] ``` -------------------------------- ### Import Dunai MSF Module in GHCi Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Opens a GHCi session and imports the main Dunai module for using Monadic Stream Functions (MSFs). ```haskell $ ghci ghci> import Data.MonadicStreamFunction ``` -------------------------------- ### Dynamic Switching with switch and dSwitch in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Shows how to implement dynamic switching between different MSFs based on events. The `switch` combinator allows an MSF to transition to a new MSF, determined by an event emitted from the current MSF, similar to Yampa's behavior. ```haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.Except -- Switch from one MSF to another when condition met switchingMSF :: Monad m => MSF m Int Int switchingMSF = switch firstPhase secondPhase where -- First phase: double, emit event when > 10 firstPhase = arr $ \x -> let doubled = x * 2 in (doubled, if doubled > 10 then Just doubled else Nothing) -- Second phase: add the switch value secondPhase switchVal = arr (+ switchVal) main :: IO () main = do result <- embed switchingMSF [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print result -- First phase doubles until result > 10, then switches -- Output: [2, 4, 6, 8, 10, 24, 26, 28, 30, 32] -- (After 5*2=10, switches. 6+12=18 should be next but depends on exact switch point) ``` -------------------------------- ### Lift Monadic Computation without Arguments into MSF Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Shows how to lift a monadic computation that takes no arguments (like `getLine`) into an MSF using `constM`. This MSF will execute the monadic action each time it is called. ```haskell ghci> :type getLine getLine :: IO String ghci> :type constM getLine constM getLine :: MSF IO a String ``` -------------------------------- ### Discard MSF Outputs using Control.Monad.void Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Illustrates how to run an MSF with side effects (using `arrM print`) and discard the resulting output list by using `Control.Monad.void`. Dunai's `embed_` provides similar functionality. ```haskell ghci> import Control.Monad (void) ghci> void $ embed (arrM print) [1,2,3,4,5] 1 2 3 4 5 ``` -------------------------------- ### Convert Monadic Function to MSF and Embed Inputs Source: https://github.com/ivanperez-keera/dunai/blob/develop/README.md Shows how to lift a monadic function (like `print`) into an MSF using `arrM`. The `embed` function then runs this MSF, executing the side effect (printing) for each input and collecting the results. ```haskell ghci> :type print print :: Show a => a -> IO () ghci> :type arrM print arrM print :: Show a => MSF IO a () ghci> embed (arrM print) [1,2,3,4,5] 1 2 3 4 5 [(), (), (), (), ()] ``` -------------------------------- ### Async Stream Processing with concatS in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Demonstrates how to flatten a stream of lists into a single, flat stream of elements using `concatS`. This is useful for processing batched data asynchronously, where each batch is generated and then its elements are processed sequentially. ```haskell import Data.MonadicStreamFunction import Data.MonadicStreamFunction.Async -- Type alias for clarity type MStream m a = MSF m () a -- Create stream from list generator batchStream :: MStream IO [Int] batchStream = constM $ do putStrLn "Generating batch..." return [1, 2, 3] -- Flatten batches into individual elements flatStream :: MStream IO Int flatStream = concatS batchStream main :: IO () main = do -- Take first 9 elements (3 batches) result <- embed flatStream $ replicate 9 () print result -- Output: -- Generating batch... -- Generating batch... -- Generating batch... -- [1, 2, 3, 1, 2, 3, 1, 2, 3] ``` -------------------------------- ### Lifting Monadic Functions with arrM in Haskell Source: https://context7.com/ivanperez-keera/dunai/llms.txt Shows how to use `arrM` to lift a monadic function (like `print`) into an MSF. This allows MSFs to perform side-effecting computations for each input element. The `embed` function is used to run the MSF. ```haskell import Data.MonadicStreamFunction import Control.Monad (void) -- Lift print into an MSF printMSF :: Show a => MSF IO a () printMSF = arrM print -- Run side-effecting MSF main :: IO () main = do void $ embed printMSF [1, 2, 3, 4, 5] -- Output: -- 1 -- 2 -- 3 -- 4 -- 5 ``` -------------------------------- ### Bouncing Ball Simulation with BearRiver (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt Implements a bouncing ball simulation using BearRiver, which provides a Yampa compatibility layer on top of Dunai. It defines signal functions for falling and bouncing balls, including gravity and energy loss on impact. Dependencies include FRP.BearRiver. ```Haskell {-# LANGUAGE Arrows #} import FRP.BearRiver -- Signal function for a bouncing ball simulation type SF m a b = MSF (ReaderT DTime m) a b -- Ball physics: position and velocity fallingBall :: Monad m => Double -> Double -> SF m () (Double, Double) fallingBall p0 v0 = proc () -> do v <- (v0 +) ^<< integral -< (-9.8) -- velocity with gravity p <- (p0 +) ^<< integral -< v -- position from velocity returnA -< (p, v) -- Bouncing ball with switching bouncingBall :: Monad m => Double -> Double -> SF m () (Double, Double) bouncingBall p0 v0 = switch (proc () -> do (p, v) <- fallingBall p0 v0 -< () bounce <- edge -< (p <= 0 && v < 0) returnA -< ((p, v), bounce `tag` (p, v))) (\(p, v) -> bouncingBall p (-v * 0.8)) -- bounce with energy loss -- Event handling edgeDetection :: Monad m => SF m Bool (Event ()) edgeDetection = edge -- Time-based signal timeSignal :: Monad m => SF m a DTime timeSignal = time ``` -------------------------------- ### Logging Operations with Writer Monad (Haskell) Source: https://context7.com/ivanperez-keera/dunai/llms.txt Demonstrates using the Writer monad transformer with Dunai's MSFs to log operation counts. The `loggingMSF` function increments a counter for each operation and doubles the input value. `runWriterS` is used to execute the MSF and collect logs. Dependencies include Data.MonadicStreamFunction, Control.Monad.Trans.MSF.Writer, and Data.Monoid. ```Haskell import Data.MonadicStreamFunction import Control.Monad.Trans.MSF.Writer import Data.Monoid (Sum(..)) -- MSF that logs operation counts loggingMSF :: MSF (WriterT (Sum Int) IO) Int Int loggingMSF = arrM $ \x -> do tell (Sum 1) -- Log one operation return (x * 2) -- Run and collect logs main :: IO () main = do let msf = runWriterS loggingMSF result <- embed msf [1, 2, 3, 4, 5] print result -- Output: [(Sum 1, 2), (Sum 1, 4), (Sum 1, 6), (Sum 1, 8), (Sum 1, 10)] -- Each tuple is (log, output) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.