monad p2: state monad examples (2c) · state monad examples (2c) 9 young won lim 7/6/19 import...

42
1 Young Won Lim 7/6/191 Monad P2: State Monad Examples (2C)

Upload: others

Post on 29-Oct-2019

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

1 Young Won Lim7/6/191

Monad P2: State Monad Examples (2C)

Page 2: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

2 Young Won Lim7/6/192

Copyright (c) 2016 - 2019 Young W. Lim. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".

Please send corrections (or suggestions) to [email protected].

This document was produced by using LibreOffice.

Page 3: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

3 Young Won Lim7/6/19

Based on

Haskell in 5 steps

https://wiki.haskell.org/Haskell_in_5_steps

Page 4: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

4 Young Won Lim7/6/19

https://wiki.haskell.org/State_Monad

Game Example

Page 5: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

5 Young Won Lim7/6/19

Passes a string of dictionary {a,b,c}

Game is to produce a number from the string.

By default the game is off,

a ‘c’ toggles the game on and off.

a 'a' gives +1 and

a ‘b’ gives -1.

'ab' = 0 +1-1=0

'ca' = 1 on, +1

'cabca' = 0 on,+1-1,off

State = (game is on/off, current score) = (Bool, Int)

https://wiki.haskell.org/State_Monad

Game Example (1)

Example use of State monad

Page 6: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

6 Young Won Lim7/6/19

module StateGame where

import Control.Monad.State

type GameValue = Int

type GameState = (Bool, Int)

playGame :: String -> State GameState GameValue

playGame [] = do

(_, score) <- get

return score

https://wiki.haskell.org/State_Monad

Game Example (2)

State s a

when input string is null

Page 7: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

7 Young Won Lim7/6/19

playGame :: String -> State GameState GameValue

playGame (x : xs) = do

(on, score) <- get

case x of

'a' | on -> put (on, score + 1)

'b' | on -> put (on, score - 1)

'c' -> put (not on, score)

_ -> put (on, score)

playGame xs

startState = (False, 0)

https://wiki.haskell.org/State_Monad

Game Example (3)

when input string is not null

Page 8: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

8 Young Won Lim7/6/19

main = print $ evalState (playGame "abcaaacbbcabbab") startState

a (off, 0) b (off, 0) c (on, 0)

a (on, 1) a (on, 2) a (on, 3)

c (off, 3) b (off, 3) b (off, 3)

c (on, 3) a (on, 4) b (on, 3)

b (on, 2) a (on, 3) b (on, 2)

https://wiki.haskell.org/State_Monad

Game Example (4)

Page 9: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

9 Young Won Lim7/6/19

import Control.Monad.State

type GameValue = Inttype GameState = (Bool, Int) playGame :: String -> State GameState GameValueplayGame [] = do (_, score) <- get return score

*Main> runState (playGame "abcaaacbbcabbab") startState(2,(True,2))*Main> execState (playGame "abcaaacbbcabbab") startState(True,2)*Main> evalState (playGame "abcaaacbbcabbab") startState2

https://wiki.haskell.org/State_Monad

Game Example Source Code

playGame (x : xs) = do (on, score) <- get case x of 'a' | on -> put (on, score + 1) 'b' | on -> put (on, score - 1) 'c' -> put (not on, score) _ -> put (on, score) case x of 'a' | on -> return $ score + 1 'b' | on -> return $ score - 1 'c' -> return $ score _ -> return score playGame xs startState = (False, 0::Int)

Page 10: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

10 Young Won Lim7/6/19

https://wiki.haskell.org/State_Monad

Incrementer Example

Page 11: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

11 Young Won Lim7/6/19

-- a concrete and simple example of using the State monad

-- non monadic version of a very simple state example

-- the State is an integer.

-- the value will always be the negative of of the state

import Control.Monad.State

type MyState = Int

type MyStateMonad = State MyState

https://wiki.haskell.org/State_Monad

Incrementer Example (1)

Page 12: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

12 Young Won Lim7/6/19

valFromState :: MyState -> Int

valFromState s = -s

nextState :: MyState->MyState

nextState x = 1+x

-- this is it, the State transformation.

-- add 1 to the state, return -1*the state as the computed value.

getNext :: MyStateMonad Int

getNext = state (\st -> let st' = nextState(st) in (valFromState(st'),st') )

https://wiki.haskell.org/State_Monad

Incrementer Example (2)

State

State Int Int

IntMyState

(Int, Int)Int

valFromState

MyStateMyState

nextState

-ss

s+1s

s (-s. s+1)

getNext

Page 13: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

13 Young Won Lim7/6/19

-- advance the state three times.

inc3::MyStateMonad Int

inc3 = getNext >>= \x ->

getNext >>= \y ->

getNext >>= \z ->

return z

https://wiki.haskell.org/State_Monad

Incrementer Example – (a) inc3

Page 14: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

14 Young Won Lim7/6/19

-- advance the state three times with do sugar

inc3Sugared::MyStateMonad Int

inc3Sugared = do x <- getNext

y <- getNext

z <- getNext

return z

https://wiki.haskell.org/State_Monad

Incrementer Example – (b) inc3Sugard

Page 15: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

15 Young Won Lim7/6/19

-- advance the state three times without inspecting computed values

inc3DiscardedValues::MyStateMonad Int

inc3DiscardedValues = getNext >> getNext >> getNext

https://wiki.haskell.org/State_Monad

Incrementer Example – (c) inc3DiscardedValues

Page 16: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

16 Young Won Lim7/6/19

-- advance the state three times

-- without inspecting computed values with do sugar

inc3DiscardedValuesSugared::MyStateMonad Int

inc3DiscardedValuesSugared = do

getNext

getNext

getNext

https://wiki.haskell.org/State_Monad

Incrementer Example – (d) inc3DiscardedValuesSugared

Page 17: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

17 Young Won Lim7/6/19

-- advance state 3 times, compute the square of the state

inc3AlternateResult::MyStateMonad Int

inc3AlternateResult = do getNext

getNext

getNext

s <- get

return (s*s)

https://wiki.haskell.org/State_Monad

Incrementer Example – (e) inc3AlternateResult

Page 18: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

18 Young Won Lim7/6/19

-- advance state 3 times, ignoring computed value, and then once more

inc4::MyStateMonad Int

inc4 = do

inc3AlternateResult

getNext

https://wiki.haskell.org/State_Monad

Incrementer Example – (f) inc4

Page 19: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

19 Young Won Lim7/6/19

main =

do

print (evalState inc3 0) -- -3

print (evalState inc3Sugared 0) -- -3

print (evalState inc3DiscardedValues 0) -- -3

print (evalState inc3DiscardedValuesSugared 0) -- -3

print (evalState inc3AlternateResult 0) -- 9

print (evalState inc4 0) -- -4

https://wiki.haskell.org/State_Monad

Incrementer Example – (g) main

Page 20: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

20 Young Won Lim7/6/19

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

Roll Dice Example

Page 21: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

21 Young Won Lim7/6/19

import System.Random

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

(a, a) : range (a, g) : output

R in randomR a : type of a random number

g : type of a seed

g : input seed

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

randomR type signature

cabal update

cabal install random

Page 22: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

22 Young Won Lim7/6/19

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

randomR (1, 6) :: StdGen -> (Int, StdGen)

assume a is Int g is StdGen

(a, a) : range of (a, g)

(Int, StdGen)

(a random value, a new seed)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

randomR type signature example

Page 23: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

23 Young Won Lim7/6/19

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

randomR updates (generates) a seed

newStdGen or mkStdGen can used

to generate an initial input seed

the type of seed is StdGen

the StdGen type :

an instance of RandomGen and Random

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

randomR – updates a seed

random number

g -> (a, g)

taking returning old seed updated seed

newStdGenmkStdGen

Page 24: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

24 Young Won Lim7/6/19

import System.Random

randomR (1, 6) :: StdGen -> (Int, StdGen)

randomR is a state processing function

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

randomR – a state processing function

(Int, StdGen)StdGen

(a, s)s

randomR

(1, 6)

State

State StdGen Int

(Int, StdGen)StdGen

Page 25: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

25 Young Won Lim7/6/19

newtype State s a = State { runState :: s -> (a, s) } (1)

newtype State s a = state { runState :: s -> (a, s) } (2)

1) let stst = State { runState = (\y -> (y, y+1)) }

2) let stst = state (\y -> (y, y+1))

runState stst (\y -> (y, y+1)) -- no instance error

runState stst 1 (1, 2)

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

runState rollDie StdGen -> (Int, StdGen)

runState rollDie (mkStdGen 1) (6, 80028 40692)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

randomR – runState, state

state(s -> (a, s)) State s a

runState(s -> (a, s))State s a

(\y -> (y, y+1))

randomR (1, 6)

(a, s)s

anonymous function

StdGen -> (Int, StdGen)

Page 26: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

26 Young Won Lim7/6/19

randomRIO returns a random number directly

in the IO monad, without explicitly using a seed of type StdGen

import System.Random

randomRIO (1, 10)

6

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

randomRIO :: (a, a) -> IO a

randomIO :: IO a

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

randomRIO

Page 27: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

27 Young Won Lim7/6/19

randomR :: RandomGen g => (a, a) -> g -> (a, g)

random :: RandomGen g => g -> (a, g)

randomRs :: RandomGen g => (a, a) -> g -> [a]

randoms :: RandomGen g => g -> [a]

randomRIO :: (a, a) -> IO a

randomIO :: IO a

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

randomRIO :: (a, a) -> IO a

randomIO :: IO a

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Methods of the random class

(6, 80028 40692)

6

6

Page 28: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

28 Young Won Lim7/6/19

mkStdGen :: Int -> StdGen

an alternative way of producing an initial generator,

by mapping an Int into a generator.

distinct Int arguments should be likely

to produce distinct generators.

newStdGen :: IO StdGen

Applies split to the current global random generator,

updates it with one of the results, and returns the other.

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Making a new seed

mkStdGen 11

12 1

newStdGen

420454863 2147483398 actual seed

mkStdGen 11

12 1

mkStdGen 12

13 1

mkStdGen 132

133 1

Page 29: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

29 Young Won Lim7/6/19

data StdGen = StdGen !Int32 !Int32 -- 2 32-bit integers

show :: a -> String

read :: String -> a

show converts a data value of two 32-bit number into a string

read converts a string into a data value of two 32-bit number

read (show g) == g -- a constraint

g :: StdGen -- a seed

reads may be used to map an arbitrary string

(not necessarily one produced by show) onto a value of type StdGen.

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

StdGen Type

! -- a strict declaration

420454863 2147483398 an actual seed

two 32-bit Int’s

in in

mkStdGen randomR

12 1 a string

show read

Page 30: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

30 Young Won Lim7/6/19

to generate a random number with a seed

type StdGen must be used,

randomR is used to generate a number

newStdGen is used to create a new seed

(this will have to be done in IO).

import System.Random

g = newStdGen

randomR (1, 10) g

(1,1012529354 2147442707)

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Generating a random number (1)

A seed of the type StdGen

A new seed is generated

by newStdGen

The result of randomR is a tuple

(a random value, the new seed)

a random value = 1

the new seed =

1012529354 2147442707

Page 31: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

31 Young Won Lim7/6/19

g = mkStdGen 58

(x1, y1) =randomR (0,100) g

x1 62 random number

y1 2360826 40692 updated seed (two 32bit Int’s)

g 59 1 string representation

randomR (0,100) g (62,2360826 40692)

(x1, y1) (62,2360826 40692)

x1 62

y1 2360826 40692

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Generating a random number (2)

A seed of the type StdGen

A seed is generated

by mkStdGen

The result of randomR is a tuple

(a random value, the new seed)

Page 32: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

32 Young Won Lim7/6/19

randomRIO (1, 6::Int) 4

randomRIO (1, 6::Int) 2

randomIO :: IO Float 0.24931645

randomIO :: IO Float 0.1068542

https://lotz84.github.io/haskellbyexample/ex/random-numbers

Generating a random number (3)

s1 = mkStdGen 55

(i1, s2) = randomR (1,6::Int) s1

(i2, _) = randomR (1,6::Int) s2

i1 6

I2 1

s1 = mkStdGen 55 -- same seed

(i1, s2) = randomR (1,6::Int) s1

(i2, _) = randomR (1,6::Int) s2

i1 6

i2 1

Page 33: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

33 Young Won Lim7/6/19

GHCi> :m System.Random

GHCi> let generator = mkStdGen 0 -- "0" is our seed

GHCi> :t generator

generator :: StdGen

GHCi> generator

1 1

GHCi> :t random

random :: (RandomGen g, Random a) => g -> (a, g)

GHCi> random generator :: (Int, StdGen)

(2092838931,1601120196 1655838864)

( Int , StdGen )

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Without using IO (1) – use random / randomR

A seed of the type StdGen

A new seed is generated

by newStdGen

Page 34: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

34 Young Won Lim7/6/19

GHCi> let randInt = fst . random $ generator :: Int

GHCi> randInt

2092838931

GHCi> let (randInt, generator') = random generator :: (Int, StdGen)

GHCi> randInt -- Same value

2092838931

GHCi> random generator' :: (Int, StdGen)

(-2143208520,439883729 1872071452)

-- Using new generator' returned from “random generator”

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Without using IO (2)

(2092838931,1601120196 1655838864)

(2092838931,1601120196 1655838864)

(-2143208520,439883729 1872071452)

Page 35: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

35 Young Won Lim7/6/19

The result type : Int dice : a number between 1 and 6

The state type : a pseudo-random generator of type StdGen

the type of the state processors will be

State StdGen Int State s a

StdGen -> (Int, StdGen) s -> (a, s)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

Dice Example – State

Page 36: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

36 Young Won Lim7/6/19

import Control.Monad.Trans.State

import System.Random

randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)

randomR (1, 6) :: StdGen -> (Int, StdGen)

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

rollDie

State

RandomR(Int, StdGen)StdGen

(Int, StdGen)StdGen

(1,6)

State StdGen IntrollDie

Page 37: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

37 Young Won Lim7/6/19

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

rollDie :: State StdGen Int

rollDie = do

gen <- get

let (val, nGen) = randomR (1,6) gen

put nGen

return value

GHCi> evalState rollDie (mkStdGen 0)

6

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

rollDie with get, put, return

State(gen, gen)gen

(val, nGen)gen

State((), nGen)gen

State(val, nGen)gen

gen <- get

let (val, nGen) = randomR (1,6) gen

put nGen

return value

Page 38: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

38 Young Won Lim7/6/19

GHCi> randomR (1,6) (mkStdGen 0)

(6, 40014 40692)

The resulting tuple combines

the result of throwing a single die with a new generator.

A simple implementation for throwing two dice is then:

clumsyRollDice :: (Int, Int)

clumsyRollDice = (n, m)

where

(n, g) = randomR (1,6) (mkStdGen 0)

(m, _) = randomR (1,6) g

https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell

Clumsy rollDice without IO

A seed of the type StdGen

A new seed is generated

by newStdGen

Page 39: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

39 Young Won Lim7/6/19

rollDice :: State StdGen (Int, Int)

rollDice = liftA2 (,) rollDie rollDie

GHCi> evalState rollDice (mkStdGen 123)

(6,1)

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

rollDice (1)

Page 40: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

40 Young Won Lim7/6/19

rollDice :: State StdGen (Int, Int)

rollDice = liftA2 (,) rollDie rollDie

rollDie :: State StdGen Int

rollDie = state $ randomR (1, 6)

That function rolls two dice.

rollDice = liftA2 (,) (randomRIO (1,6)) (randomRIO (1,6))

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

rollDice (2)

Page 41: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

41 Young Won Lim7/6/19

liftA2 makes the two-argument function ( , )

work within a monad or applicative functor, IO, rollDie.

( , ) is the non-infix version of the tuple constructor.

the two die rolls will be returned as a tuple in IO

liftA2 f u v = f <$> u <*> v

rollDice = (,) <$> rollDie <*> rollDie

https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

rollDice (3)

State(Int, StdGen)StdGen

State StdGen IntrollDie

State StdGen Int State StdGen Int

( , )liftA2

State StdGen (Int, Int)

Page 42: Monad P2: State Monad Examples (2C) · State Monad Examples (2C) 9 Young Won Lim 7/6/19 import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playGame :: String

State Monad Examples (2C)

42 Young Won Lim7/6/19

References

[1] ftp://ftp.geoinfo.tuwien.ac.at/navratil/HaskellTutorial.pdf

[2] https://www.umiacs.umd.edu/~hal/docs/daume02yaht.pdf