State Monad Examples (6C) Young Won Lim 9/22/18

Similar documents
State Monad Examples (6C) Young Won Lim 9/26/18

State Monad Example (3H) Young Won Lim 2/16/18

State Monad (3D) Young Won Lim 8/31/17

State Monad (3D) Young Won Lim 9/25/17

IO Monad (3D) Young Won Lim 1/18/18

Applicatives Comparisons (2C) Young Won Lim 3/6/18

Monad Overview (3B) Young Won Lim 1/16/18

IO Monad (3C) Young Won Lim 1/6/18

Background Expressions (1D) Young Won Lim 7/7/18

Side Effects (3B) Young Won Lim 11/20/17

Side Effects (3B) Young Won Lim 11/23/17

Haskell Overview II (2A) Young Won Lim 8/9/16

Side Effects (3B) Young Won Lim 11/27/17

Background Type Classes (1B) Young Won Lim 6/14/18

Side Effects (3A) Young Won Lim 1/13/18

Monad Background (3A) Young Won Lim 10/5/17

Background Operators (1E) Young Won Lim 7/7/18

Haskell Overview II (2A) Young Won Lim 9/26/16

Polymorphism Overview (1A) Young Won Lim 2/20/18

Monad Background (3A) Young Won Lim 11/8/17

Haskell Overview IV (4A) Young Won Lim 10/24/16

Monad (1A) Young Won Lim 6/26/17

CIS 194: Homework 11. Due Thursday, April 5. Risk. The Rand StdGen monad

Monad Background (3A) Young Won Lim 11/18/17

Background Type Classes (1B) Young Won Lim 6/28/18

Monad (1A) Young Won Lim 6/9/17

IO Monad (3C) Young Won Lim 8/23/17

Haskell Overview II (2A) Young Won Lim 8/23/16

GHCi: Getting started (1A) Young Won Lim 5/26/17

GHCi: Getting started (1A) Young Won Lim 6/3/17

Background Functions (1C) Young Won Lim 5/26/18

Haskell Overview III (3A) Young Won Lim 10/4/16

Libraries (1A) Young Won Lim 6/5/17

Monad Background (3A) Young Won Lim 11/20/17

Monads. Functional Programming (CS4011) Monads

Monad (1A) Young Won Lim 6/21/17

Monad (3A) Young Won Lim 8/9/17

Background Constructors (1A) Young Won Lim 7/9/18

Haskell Overview IV (4A) Young Won Lim 10/13/16

Binary Search Tree (2A) Young Won Lim 5/17/18

Monads and all that I. Monads. John Hughes Chalmers University/Quviq AB

A Sudoku Solver (1A) Richard Bird Implementation. Young Won Lim 11/15/16

A Sudoku Solver Pruning (3A)

Algorithms Bubble Sort (1B) Young Won Lim 4/5/18

Operators (2A) Young Won Lim 10/2/13

Logic Haskell Exercises

Monoid (4A) Young Won Lim 8/12/17

The Complexity of Algorithms (3A) Young Won Lim 4/3/18

Maybe Monad (3B) Young Won Lim 12/21/17

Solution sheet 1. Introduction. Exercise 1 - Types of values. Exercise 2 - Constructors

GHCi: Getting started (1A) Young Won Lim 5/31/17

Background Constructors (1A) Young Won Lim 6/30/18

Operators (2A) Young Won Lim 10/5/13

An Introduction to Programming in Haskell. Gabriel J. Ferrer Hendrix College

Pointers (1A) Young Won Lim 11/1/17

Applications of Arrays (1A) Young Won Lim 3/15/17

Background Constructors (1A) Young Won Lim 1/22/18

Pointers (1A) Young Won Lim 3/5/18

CS 320: Concepts of Programming Languages

Applications of Arrays (1A) Young Won Lim 2/11/17

Background Constructors (1A) Young Won Lim 7/5/18

Applications of Pointers (1A) Young Won Lim 12/26/17

Functions (4A) Young Won Lim 5/8/17

Binary Search Tree (3A) Young Won Lim 6/2/18

Maybe Monad (3B) Young Won Lim 1/3/18

Pointers (1A) Young Won Lim 1/5/18

Pointers (1A) Young Won Lim 1/9/18

INDEX. Symbols & Numbers. Learn You a Haskell for Great Good! 2011 by Miran Lipovača

Accessibility (1A) Young Won Lim 8/22/13

Overview (1A) Young Won Lim 9/14/17

Pointers (1A) Young Won Lim 1/22/18

Applications of Pointers (1A) Young Won Lim 4/24/18

Overview (1A) Young Won Lim 9/9/17

Day06 A. Young W. Lim Mon. Young W. Lim Day06 A Mon 1 / 16

Background Functions (1C) Young Won Lim 4/3/18

Functions (4A) Young Won Lim 3/16/18

Function Overview (1A) Young Won Lim 10/23/17

Introduction to Haskell

Overview (1A) Young Won Lim 9/25/17

Arrays (1A) Young Won Lim 12/4/17

Applications of Pointers (1A) Young Won Lim 2/27/18

Eulerian Cycle (2A) Young Won Lim 4/26/18

Class (1A) Young Won Lim 9/8/14

GAS Tutorial - 6. Expression

Applications of Pointers (1A) Young Won Lim 3/14/18

Applications of Pointers (1A) Young Won Lim 3/21/18

Haskell An Introduction

Applications of Pointers (1A) Young Won Lim 3/31/18

1 Delimited continuations in Haskell

Binary Search Tree (3A) Young Won Lim 6/4/18

Pointers (1A) Young Won Lim 2/6/18

Binary Search Tree (3A) Young Won Lim 6/6/18

Functional Programming for Logicians - Lecture 1

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

Haskell Monads CSC 131. Kim Bruce

Applications of Pointers (1A) Young Won Lim 4/11/18

Pointers (1A) Young Won Lim 2/10/18

Trees. Solution: type TreeF a t = BinF t a t LeafF 1 point for the right kind; 1 point per constructor.

Day05 A. Young W. Lim Sat. Young W. Lim Day05 A Sat 1 / 14

Logical Methods in... using Haskell Getting Started

Transcription:

State Monad s (6C)

Copyright (c) 2016-2018 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 youngwlim@hotmail.com. This document was produced by using LibreOffice.

Based on Haskell in 5 steps https://wiki.haskell.org/haskell_in_5_steps 3

Game (1) 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. use of State monad '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 4

Game (2) 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 State s a when input string is null https://wiki.haskell.org/state_monad 5

Game (3) 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 when input string is not null startstate = (False, 0) https://wiki.haskell.org/state_monad 6

Game (4) 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 7

Game Source Code import Control.Monad.State type GameValue = Int type GameState = (Bool, Int) playgame :: String -> State GameState GameValue playgame [] = do (_, score) <- get return score 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) *Main> runstate (playgame "abcaaacbbcabbab") startstate (2,(True,2)) *Main> execstate (playgame "abcaaacbbcabbab") startstate (True,2) *Main> evalstate (playgame "abcaaacbbcabbab") startstate 2 https://wiki.haskell.org/state_monad 8

Incrementer (1) -- 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 9

Incrementer (2) 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. valfromstate MyState s nextstate MyState s Int -s MyState s+1 getnext :: MyStateMonad Int getnext = state (\st -> let st' = nextstate(st) in (valfromstate(st'),st') ) getnext State Int s State Int Int (Int, Int) (-s. s+1) https://wiki.haskell.org/state_monad 10

Incrementer (a) inc3 -- advance the state three times. inc3::mystatemonad Int inc3 = getnext >>= \x -> getnext >>= \y -> getnext >>= \z -> return z https://wiki.haskell.org/state_monad 11

Incrementer (b) inc3sugard -- 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 12

Incrementer (c) inc3discardedvalues -- advance the state three times without inspecting computed values inc3discardedvalues::mystatemonad Int inc3discardedvalues = getnext >> getnext >> getnext https://wiki.haskell.org/state_monad 13

Incrementer (d) inc3discardedvaluessugared -- 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 14

Incrementer (e) inc3alternateresult -- 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 15

Incrementer (f) inc4 -- advance state 3 times, ignoring computed value, and then once more inc4::mystatemonad Int inc4 = do inc3alternateresult getnext https://wiki.haskell.org/state_monad 16

Incrementer (g) main 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 17

randomr type signature import System.Random randomr :: (Random a, RandomGen g) => (a, a) -> g -> (a, g) cabal update cabal install random (a, a) : range (a, g) : output a : type of a random number g : type of an updated seed https://en.wikibooks.org/wiki/haskell/understanding_monads/state 18

randomr seed import System.Random randomr :: (Random a, RandomGen g) => (a, a) -> g -> (a, g) the type of seed is StdGen an input seed can be generated by newstdgen or mkstdgen the StdGen type : an instance of RandomGen and Random https://en.wikibooks.org/wiki/haskell/understanding_monads/state 19

randomr type signature example import System.Random randomr :: (Random a, RandomGen g) => (a, a) -> g -> (a, g) randomr (1, 6) :: StdGen -> (Int, StdGen) assume a is Int (a, a) : range of (a, g) g is StdGen (Int, StdGen) (a random value, a new seed) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 20

randomr a state processing function import System.Random randomr (1, 6) :: StdGen -> (Int, StdGen) s (a, s) randomr a state processing function rolldie :: State StdGen Int rolldie = state $ randomr (1, 6) itself a stateful computation StdGen (Int, StdGen) randomr (1, 6) State StdGen Int State StdGen (Int, StdGen) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 21

randomr runstate, state newtype State s a = State { runstate :: s -> (a, s) } (1) newtype State s a = state { runstate :: s -> (a, s) } (2) (s -> (a, s)) State s a state 1) let stst = State { runstate = (\y -> (y, y+1)) } State s a runstate (s -> (a, s)) 2) let stst = state (\y -> (y, y+1)) runstate stst runstate stst 1 (1, 2) (\y -> (y, y+1)) -- no instance error anonymous function (\y -> (y, y+1)) randomr (1, 6) rolldie :: State StdGen Int rolldie = state $ randomr (1, 6) s (a, s) a = Int, s = StdGen https://en.wikibooks.org/wiki/haskell/understanding_monads/state 22

randomrio Otherwise, you can use randomrio to get a random number directly in the IO monad, Without explicitly using a seed of type StdGen import System.Random randomrio (1, 10) 6 https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell 23

Generating a random number (1) 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) 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 randomr :: (Random a, RandomGen g) => (a, a) -> g -> (a, g) https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell 24

Generating a random number (2) g = mkstdgen 58 (x1, y1) =randomr (0,100) g x1 62 y1 2360826 40692 g 59 1 randomr (0,100) g (62,2360826 40692) (x1, y1) (62,2360826 40692) x1 62 y1 2360826 40692 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) https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell 25

Generating a random number (3) randomrio (1, 6::Int) 4 randomrio (1, 6::Int) 2 randomio :: IO Float 0.24931645 randomio :: IO Float 0.1068542 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 https://lotz84.github.io/haskellbyexample/ex/random-numbers 26

Dice State 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 27

rolldie import Control.Monad.Trans.State import System.Random randomr :: (Random a, RandomGen g) => (a, a) -> g -> (a, g) randomr (1, 6) :: StdGen -> (Int, StdGen) StdGen RandomR (1,6) (Int, StdGen) rolldie State StdGen Int rolldie :: State StdGen Int rolldie = state $ randomr (1, 6) State StdGen (Int, StdGen) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 28

rolldie with get, put, return 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 gen <- get State gen (gen, gen) let (val, ngen) = randomr (1,6) gen gen (val, ngen) put ngen State gen ((), ngen) return value State gen (val, ngen) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 29

rolldice (1) rolldice :: State StdGen (Int, Int) rolldice = lifta2 (,) rolldie rolldie GHCi> evalstate rolldice (mkstdgen 123) (6,1) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 30

rolldice (2) rolldice :: State StdGen (Int, Int) rolldie State StdGen Int rolldice = lifta2 (,) rolldie rolldie State StdGen (Int, StdGen) That function rolls two dice. Here, lifta2 is used to make the two-argument function (, ) work within a monad or applicative functor, in this case IO. It can be easily defined in terms of (<*>): State StdGen Int State StdGen Int lifta2 f u v = f <$> u <*> v lifta2 (, ) As for (, ), it is the non-infix version of the tuple constructor. That being so, the two die rolls will be returned as a tuple in I State StdGen (Int Int) https://en.wikibooks.org/wiki/haskell/understanding_monads/state 31

Removing IO randomr (1, 6) :: StdGen -> (Int, StdGen) 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) A seed of the type StdGen A new seed is generated by newstdgen https://stackoverflow.com/questions/8416365/generate-a-random-integer-in-a-range-in-haskell 32

Removing IO 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 33

Dice without IO 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: A seed of the type StdGen A new seed is generated by newstdgen 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 34

References [1] ftp://ftp.geoinfo.tuwien.ac.at/navratil/haskelltutorial.pdf [2] https://www.umiacs.umd.edu/~hal/docs/daume02yaht.pdf