4xx
4xx

Reputation: 185

Haskell: State Monad

I'm trying to learn Haskell. I wrote a code that uses a global state and can change it using two functions (i.e. change1 and change 2). Also, I have included lens so I can learn it too. The problem is very last line of the code. I don't understand why I cannot include the two last lines together in the main. It'd run if I remove either of them.

{-# LANGUAGE TemplateHaskell #-}

module Dd (main, ma, change1,change2, Dp(Dp))  where
import Control.Lens
import Control.Monad.State
import Control.Monad.IO.Class (liftIO)

data Dp = Dp {_sr  :: Int , _fl :: Int} deriving (Show)
makeLenses ''Dp

plus ::  Dp  -> Dp
plus  = over (sr) (+90)

mult4 ::  Dp  -> Dp
mult4 = over (fl) (*100)

change1 :: State Dp ()
change1 = modify plus

change2 :: State Dp () 
change2  = modify  mult4 

ma :: State Dp ()
ma  = do 
      change1
      change2 

main = do 
     runState ma (Dp 2 3)
     evalState ma (Dp 2 3)-- here is the problem

Edit: I'm a bit confused: Why below code runs without an error?

data Dp = Dp {_sr  :: Int , _fl :: Int} deriving (Show)

makeLenses ''Dp
gs :: StateT Dp IO Int
gs = do 
d <- gets _sr
liftIO $ print (d)
dd<- uses sr (10<=)
if (dd) then 
            return (10)
            else return (90)
 main  =  do 
        runStateT gs (Dp 3 6)
        evalStateT gs (Dp 3 6)

Upvotes: 1

Views: 436

Answers (1)

Igor Drozdov
Igor Drozdov

Reputation: 15045

In your case do-notation is a syntactic sugar for

(runState ma (Dp 2 3)) >> (evalState ma (Dp 2 3))

The type of (>>) is Monad m => m a -> m b -> m b which means that runState ma (Dp 2 3) and evalState ma (Dp 2 3) must be in the same monad, but they are not

But the code doesn't work mostly for another reason. The function main has the following type annotation: main :: IO a which means that main expects an action to be performed in it (for example printing the results)

main :: IO ()
main = do
  print $ runState ma (Dp 2 3)
  print $ evalState ma (Dp 2 3)

That works, because

  • type of print $ runState ma (Dp 2 3) is IO ((), Dp)
  • type of print $ evalState ma (Dp 2 3) is IO ()

Hence, inferred type for >> is IO ((), Dp) -> IO () -> IO () which doesn't violate Monad m => m a -> m b -> m b. And the resulting type is IO () which suits for main :: IO a

Upvotes: 4

Related Questions