Skip to content

Instantly share code, notes, and snippets.

@rajanaresh
Last active April 10, 2020 01:55
Show Gist options
  • Save rajanaresh/ee319f51c1a52c5c6e7c093eb1b940f6 to your computer and use it in GitHub Desktop.
Save rajanaresh/ee319f51c1a52c5c6e7c093eb1b940f6 to your computer and use it in GitHub Desktop.
Comparison b/w my implementation of FizzBuzz using my own State Monad with my own "mapM_" (myMapM_) and the implementation from the Haskell book
#!/usr/local/bin/stack
{- stack
--resolver lts-14.27
exec ghci
--package pretty-simple
-}
import Control.Monad
import Control.Monad.Trans.State
fizzBuzz :: Integer -> String
fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Buzz"
| n `mod` 3 == 0 = "Fizz"
| otherwise = show n
fizzBuzzList :: [Integer] -> [String]
fizzBuzzList ls = execState (mapM_ addResult ls) []
where addResult :: Integer -> State [String] ()
addResult n = get >>=
\s -> put (fizzBuzz n: s)
-- the main function is slightly different in the book but I am using this
main :: IO ()
main = traverse putStrLn (fizzBuzzList [1..100]) >>
return ()
#!/usr/local/bin/stack
{- stack
--resolver lts-14.27
exec ghci
--package pretty-simple
-}
newtype State s a = State { runState :: s -> (a, s) }
instance Functor (State s) where
fmap f (State sa) = State $ \s -> (f (fst (sa s)), snd (sa s))
instance Applicative (State s) where
pure x = State $ \s -> (x, s)
-- (<*>) :: State s (a -> b) -> State s a -> State s b
State sf <*> State sa = State $ \s -> ((fst (sf s)) (fst (sa s)), s)
instance Monad (State s) where
return = pure
-- (>>=) :: State s a -> a -> State s b -> State s b
-- (>>=) :: (s -> (a, s)) -> (a -> (s -> (b, s))) -> s -> (b, s)
State sa >>= aSb = State $ \s -> runState (aSb (fst (sa s))) s
myMapM_ :: (Foldable t) => (a -> State s ()) -> t a -> State s ()
myMapM_ f ls = foldr go (return ()) ls
where go x y = copy y >>= \st -> State $ \s -> runState (f x) st
fizzBuzz :: Integer -> String
fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Buzz"
| n `mod` 3 == 0 = "Fizz"
| otherwise = show n
fizzBuzzS :: Integer -> State [String] ()
fizzBuzzS n = get >>=
\s -> put (fizzBuzz n: s)
fizzBuzzList :: [Integer] -> [String]
fizzBuzzList ls = execState (myMapM_ fizzBuzzS ls) []
put :: s -> State s ()
put s = State $ \_ -> ((), s)
get :: State s s
get = State $ \s -> (s, s)
execState :: State s () -> s -> s
execState st s = snd (runState st s)
copy :: State s () -> State s s
copy st = State $ \s -> (execState st s, execState st s)
main :: IO ()
main = traverse putStrLn (fizzBuzzList [1..100]) >>
return ()
@rajanaresh
Copy link
Author

State monad implementation is wrong

Should be State sa >>= aSb = State $ \s -> runState (aSb (fst (sa s))) (snd (sa s))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment