I am working on a simple example to implement the state monad in Haskell. I have made a data type GlobState using record syntax. Functions incr1, incr2 and incr3 are there to increment the respective record elements. The code i have written is:
module StateExample where
import Control.Monad.State
data GlobState = GlobState { c1 :: Int, c2:: Int, c3:: Int} deriving (Show)
newGlobState:: GlobState
newGlobState = GlobState { c1=0,c2=0,c3=0 }
--incr1 :: State GlobState ()
incr1 = do
gets c1
modify (+1)
--incr2 :: State GlobState ()
incr2 = do
gets c2
modify(+1)
incr3 = do
gets c3
modify(+1)
main = do
let ((),a1) = flip runState newGlobState $ do
x<- incr1
y<- incr2 x
z<- incr1 y
return z
print a1
This program is not giving the desired output. And i am not sure about the signature of increment functions or if gets is doing what i intend to do. Please help.
How can i make changes to the code so that instead of defining the different increment functions, i need to make only one increment function. i intend to do like:
incr :: String-> State GlobState ()
incr x = do
modify(\g -> g {x =x g + 1})
Your types are right, at least.
Your
modify (+1)would be fine if you were working inState Int (), say, but we’re not. You seem to think thatgetsfocusses the following lines onto a particular field of the state — but it doesn’t.incr2andincr3need to be changed similarly.As to
main:print a1to be part of the outer do block, but not part of the inner do block. Without indentation, the compiler cannot figure that out.Stateis that its monadic/applicative plumbing does that for you.