Created
December 24, 2018 19:40
-
-
Save dino-/347b0f02c4acf9053ae4ff05ca891a55 to your computer and use it in GitHub Desktop.
State in Haskell is simple
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env stack | |
-- stack --resolver lts-12.24 script | |
-- If stack isn't installed on your system and you can't/won't get it, install | |
-- a reasonably-modern GHC and use this instead of the above two lines: | |
-- #! /usr/bin/env runhaskell | |
import Control.Monad.State | |
main :: IO () | |
main = do | |
{- | |
We've seen examples of how to build up the State monad by hand which is | |
helpful to understand what's happening under the State monad covers. | |
I wanted to illustrate just how minimal and simple it is to use the state | |
monad in real world code. | |
-} | |
let startingState = 0 | |
let result = runState ( do | |
addFive | |
multThree | |
) startingState | |
-- This code is operating entirely on the state, the return value, in the | |
-- left side of the tuple, is in this case a useless () value that we'll drop | |
print . snd $ result | |
{- | |
One case for using the State monad is that you're going to need the state | |
in some functions that this computation will call (signified here by | |
addFive and multThree) and passing it around explicitly will be ugly. | |
There are other reasons you may want State monad specifically but it's not | |
for everything. | |
-} | |
-- Sometimes a stateful task is too trivial for even that much code. | |
-- In simple cases, function composition will suffice | |
print $ (* 3) . (+ 5) $ 0 | |
-- Another example uses a right fold and the function application function to | |
-- thread the state through a list of functions. | |
print $ foldr ($) 0 [(* 3), (+ 5)] | |
-- All three of these examples output the same value | |
-- Functions that need the state above, no need to pass explicitly | |
addFive :: State Int () | |
addFive = do | |
n <- get | |
put $ n + 5 | |
multThree :: State Int () | |
multThree = modify (* 3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment