codesnippets:monads
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| codesnippets:monads [2022/04/21 22:18] – f2b216 | codesnippets:monads [2025/10/08 00:48] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ~~DISCUSSION~~ | ~~DISCUSSION~~ | ||
| + | |||
| ====== Monads ====== | ====== Monads ====== | ||
| + | |||
| + | ===== Example 1a ===== | ||
| + | |||
| + | * this example shows how alternative results (sum type, algebraic type, see type A, B and C in the example) can be handled and propagated in a computation by means of ' | ||
| + | * it works but it is quite some code | ||
| + | |||
| + | * Code:< | ||
| + | main :: IO () | ||
| + | main = | ||
| + | do | ||
| + | putStrLn $ show (fAListToC [(A 12), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 13), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A (-1)), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 11), (A 5), (A 13)] fAToB) | ||
| + | |||
| + | data A a = A a | AError | ANone | ||
| + | deriving Show | ||
| + | |||
| + | data B a = B a | BError | BNone | ||
| + | deriving Show | ||
| + | |||
| + | data C a = C a | CError | CNone | ||
| + | deriving Show | ||
| + | |||
| + | fAToB :: A Int -> B Int | ||
| + | fAToB (A n) | ||
| + | | n <= 0 = BNone | ||
| + | | n < 13 = B (23 `div` n) | ||
| + | | otherwise = BError | ||
| + | fAToB AError = BError | ||
| + | fAToB ANone = BNone | ||
| + | |||
| + | fAListToC :: [A a] -> (A a -> B a) -> C [a] | ||
| + | fAListToC [] _ = C [] | ||
| + | fAListToC (a@(A _):lrAList) fAToB' = | ||
| + | do | ||
| + | case fAToB' a of | ||
| + | B b -> | ||
| + | let | ||
| + | c = (fAListToC lrAList fAToB' | ||
| + | in | ||
| + | case c of | ||
| + | C lb -> C (b : lb) | ||
| + | CNone -> CNone | ||
| + | CError -> CError | ||
| + | BError -> CError | ||
| + | BNone -> CNone | ||
| + | fAListToC (AError:_) _ = CError | ||
| + | fAListToC (ANone:_) _ = CNone | ||
| + | </ | ||
| + | |||
| + | * Output:< | ||
| + | C [1,3,2,4] | ||
| + | CError | ||
| + | CNone | ||
| + | CError | ||
| + | </ | ||
| + | |||
| + | ===== Example 1b ===== | ||
| + | |||
| + | * this example does not explain monads but an alternative solution where monads usually apply | ||
| + | * it shows how alternative results (sum type, algebraic type, see type A, B and C in the example) can be handled and propagated in a computation by means of a function that handles such alternative results | ||
| + | * that function handles such results by function ' | ||
| + | |||
| + | * more detailed description of the program | ||
| + | * the function ' | ||
| + | * the transformation of data is according to function ' | ||
| + | * ' | ||
| + | * in ' | ||
| + | |||
| + | * this example compile warning free with GHC 9.2.7 using -Wall | ||
| + | |||
| + | * Code:< | ||
| + | main :: IO () | ||
| + | main = | ||
| + | do | ||
| + | putStrLn $ show (fAListToC [(A 12), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 13), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A (-1)), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 11), (A 5), (A 13)] fAToB) | ||
| + | |||
| + | data A a = A a | AError | ANone | ||
| + | deriving Show | ||
| + | |||
| + | data B a = B a | BError | BNone | ||
| + | deriving Show | ||
| + | |||
| + | data C a = C a | CError | CNone | ||
| + | deriving Show | ||
| + | |||
| + | fAToB :: A Int -> B Int | ||
| + | fAToB (A n) | ||
| + | | n <= 0 = BNone | ||
| + | | n < 13 = B (23 `div` n) | ||
| + | | otherwise = BError | ||
| + | fAToB AError = BError | ||
| + | fAToB ANone = BNone | ||
| + | |||
| + | fAListToC :: [A a] -> (A a -> B a) -> C [a] | ||
| + | fAListToC [] _ = C [] | ||
| + | fAListToC (a@(A _):lrAList) fAToB' = | ||
| + | do | ||
| + | case fAToB' a of | ||
| + | B b -> ifC (fAListToC lrAList fAToB' ) (\lb -> C (b : lb)) CNone CError | ||
| + | BError -> CError | ||
| + | BNone -> CNone | ||
| + | fAListToC (AError:_) _ = CError | ||
| + | fAListToC (ANone:_) _ = CNone | ||
| + | |||
| + | ifC :: C a -> (a -> b) -> b -> b -> b | ||
| + | ifC (C x) fThen _ _ = fThen x | ||
| + | ifC CNone _ bNone _ = bNone | ||
| + | ifC CError _ _ bError = bError | ||
| + | </ | ||
| + | |||
| + | * Output:< | ||
| + | C [1,3,2,4] | ||
| + | CError | ||
| + | CNone | ||
| + | CError | ||
| + | </ | ||
| + | |||
| + | ===== Example 1c ===== | ||
| + | |||
| + | * this example uses the instances for Functor, Applicative and Monad | ||
| + | * this way the operator '>> | ||
| + | |||
| + | * Code:< | ||
| + | import qualified Control.Monad as M (liftM, ap) | ||
| + | |||
| + | instance Functor C where | ||
| + | fmap = M.liftM | ||
| + | |||
| + | instance Applicative C where | ||
| + | pure = C | ||
| + | (<*>) = M.ap | ||
| + | |||
| + | instance Monad C where | ||
| + | CError | ||
| + | CNone >> | ||
| + | (C x) >> | ||
| + | return | ||
| + | |||
| + | main :: IO () | ||
| + | main = | ||
| + | do | ||
| + | putStrLn $ show (fAListToC [(A 12), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 13), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A (-1)), (A 7), (A 11), (A 5)] fAToB) | ||
| + | putStrLn $ show (fAListToC [(A 7), (A 11), (A 5), (A 13)] fAToB) | ||
| + | |||
| + | data A a = A a | AError | ANone | ||
| + | deriving Show | ||
| + | |||
| + | data B a = B a | BError | BNone | ||
| + | deriving Show | ||
| + | |||
| + | data C a = C a | CError | CNone | ||
| + | deriving Show | ||
| + | |||
| + | fAToB :: A Int -> B Int | ||
| + | fAToB (A n) | ||
| + | | n <= 0 = BNone | ||
| + | | n < 13 = B (23 `div` n) | ||
| + | | otherwise = BError | ||
| + | fAToB AError = BError | ||
| + | fAToB ANone = BNone | ||
| + | |||
| + | fAListToC :: [A a] -> (A a -> B a) -> C [a] | ||
| + | fAListToC [] _ = C [] | ||
| + | fAListToC (a@(A _):lrAList) fAToB' = | ||
| + | do | ||
| + | case fAToB' a of | ||
| + | B b -> fAListToC lrAList fAToB' >>= \lb -> return (b : lb) | ||
| + | BError -> CError | ||
| + | BNone -> CNone | ||
| + | fAListToC (AError:_) _ = CError | ||
| + | fAListToC (ANone:_) _ = CNone | ||
| + | </ | ||
| + | |||
| + | * Output:< | ||
| + | C [1,3,2,4] | ||
| + | CError | ||
| + | CNone | ||
| + | CError | ||
| + | </ | ||
| + | |||
| + | ===== Example 2 ===== | ||
| * inspired from https:// | * inspired from https:// | ||
| * examples compile warning free with GHC 8.10.4 using -Wall | * examples compile warning free with GHC 8.10.4 using -Wall | ||
| - | <code Haskell> | + | * Code:<code Haskell> |
| module Main where | module Main where | ||
| Line 116: | Line 305: | ||
| Empty s >> | Empty s >> | ||
| (Contains x) >>= worker = worker x | (Contains x) >>= worker = worker x | ||
| - | return | + | return |
| - | + | </ | |
| - | Output: | + | |
| - | < | + | * Output:< |
| Contains (Wrapper (Chopsticks {nPieces = 54, nQuality = Polished})) | Contains (Wrapper (Chopsticks {nPieces = 54, nQuality = Polished})) | ||
| Contains (StorageBin (Chopsticks {nPieces = 34, nQuality = Polished})) | Contains (StorageBin (Chopsticks {nPieces = 34, nQuality = Polished})) | ||
| Line 128: | Line 316: | ||
| Empty "no chopsticks at packing" | Empty "no chopsticks at packing" | ||
| </ | </ | ||
| + | |||
codesnippets/monads.1650572302.txt.gz · Last modified: (external edit)
