diff --git a/23-state/23-state.md b/23-state/23-state.md new file mode 100644 index 0000000..52438af --- /dev/null +++ b/23-state/23-state.md @@ -0,0 +1,55 @@ +# 23 State + +## 23.5 Exercises: Roll Your Own + +```haskell +repeat :: a -> [a] +repeat a = a : repeat a + +instance Functor (State s) where +fmap f st = state $ \s -> let (a, s') = runState st s + in (f a, s') + +-- Applying this to infiniteDie means that we advance the StdGen once and +-- repeat the rolled die. I.e. we only call randomR once and then repeat +-- the result. + +replicateM :: Applicative f => Int -> f a -> f [a] +replicateM n fa + | n <= 0 = pure [] + | otherwise = (:) <$> fa <*> replicateM (n - 1) fa + +instance Applicative (State s) where +pure a = state $ \s -> (a, s) +stf <*> sta = state $ \s -> let (f, s') = runState stf s + (a, s'') = runState sta s' + in (f a, s'') + +-- randomR will be called for every fmap statement in replicateM. This is +-- because we now from previous statement that fmap will call randomR and the +-- resulting State object will no longer call randomR. The second argument +-- in <*> will eventually reduce to pure [] which won't change the state and +-- call a randomR once for each fmap. +-- Hence we get an array with a call to randomR for each element, propagating +-- the StdGen forward along it. +``` + +[src/RandomExample2.hs](./src/RandomExample2.hs) + +To run in ghci: + +```shell +Prelude> :l src/RandomExample2.hs src/RandomExample.hs +``` + +## 23.6 Write `State` for yourself + +[src/Moi.hs](./src/Moi.hs) + +## 23.7 Fizzbuzz differently + +[src/fizzbuzz.hs](./src/fizzbuzz.hs) + +## 23.8 Chapter Exercises + +[src/chapter.hs](./src/chapter.hs) \ No newline at end of file diff --git a/23-state/23.5-roll-your-own.md b/23-state/23.5-roll-your-own.md deleted file mode 100644 index 169fa52..0000000 --- a/23-state/23.5-roll-your-own.md +++ /dev/null @@ -1,2 +0,0 @@ -# Exercises: Roll Your Own -see src/RandomExample2.hs \ No newline at end of file diff --git a/23-state/23.8-chapter-exercises.md b/23-state/23.8-chapter-exercises.md deleted file mode 100644 index 02acf4a..0000000 --- a/23-state/23.8-chapter-exercises.md +++ /dev/null @@ -1,2 +0,0 @@ -# Chapter Exercises -see src/chapter.hs \ No newline at end of file diff --git a/23-state/src/Moi.hs b/23-state/src/Moi.hs index 5c5d563..b38b0ce 100644 --- a/23-state/src/Moi.hs +++ b/23-state/src/Moi.hs @@ -11,10 +11,10 @@ instance Functor (Moi s) where instance Applicative (Moi s) where pure :: a -> Moi s a pure a = Moi $ \s -> (a, s) - + (<*>) :: Moi s (a -> b) -> Moi s a -> Moi s b - (Moi f) <*> (Moi g) = Moi $ \s -> let (a, s') = g s - (f', s'') = f s' + (Moi f) <*> (Moi g) = Moi $ \s -> let (f', s') = f s + (a, s'') = g s' in (f' a, s'') instance Monad (Moi s) where diff --git a/23-state/src/chapter.hs b/23-state/src/chapter.hs index 9506f8a..cfb4897 100644 --- a/23-state/src/chapter.hs +++ b/23-state/src/chapter.hs @@ -6,8 +6,8 @@ instance Functor (State s) where in (f a, s') instance Applicative (State s) where pure a = State $ \s -> (a, s) - (State f) <*> k = State $ \s -> let (a, s') = runState k s - (f', s'') = f s' + (State f) <*> k = State $ \s -> let (f', s') = f s + (a, s'') = runState k s' in (f' a, s'') instance Monad (State s) where return = pure