Reputation: 185
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
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
print $ runState ma (Dp 2 3)
is IO ((), Dp)
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