I looked at the MonadState source code, I don't understand why these 3 functions won't get into dead loop? How does this get evaluated?
class Monad m => MonadState s m | m -> s where
-- | Return the state from the internals of the monad.
get :: m s
get = state (\s -> (s, s))
-- | Replace the state inside the monad.
put :: s -> m ()
put s = state (\_ -> ((), s))
-- | Embed a simple state action into the monad.
state :: (s -> (a, s)) -> m a
state f = do
s <- get
let ~(a, s') = f s
put s'
return a
Here's the definition of get and put from Control.Monad.State.Class: -- | Return the state from the internals of the monad. get :: m s get = state (\s -> (s, s)) -- | Replace the state inside the monad. put :: s -> m () put s = state (\_ -> ( (), s)) So "get" just returns a State with a function inside of it.
State monad code looks as if the state were a global mutable variable. You access it using get with no arguments, and you modify it by calling put that returns no value. So what have we gained in comparison to C? We might not see the hidden effects, but the compiler does. It desugars every do block and type-checks it.
Whereas above we were discussing State, a concrete data type, MonadState is a new typeclass for types that are monads and for which we can define get and put operations. The class allows for a variety of Monad Transformer “stacks” that use state-passing to share a common interface for the basic state operations.
The Monad instance declaration for State looks something like this: instance Monad (State s) where return x = state (\st -> (x, st)) act >>= k = state $ \st -> let (x, st') = runState act st in runState (k x) st' Notice that State s is not a type but a type constructor: it needs one more type variable to become a type.
The definitions of get,put,state
in the class declaration are the default implementations, which are meant to be overridden in actual instances of the class. In this way, the dead loop is broken: if an instance defines only state
, then get
and put
are defined in terms of it using the default implementation in the class. Similarly, if an instance defines get
and put
, then state
is defaulted.
For instance, the Eq
type class might have been defined as follows:
class Eq a where
(==) :: a -> a -> Bool
x == y = not (x /= y)
(/=) :: a -> a -> Bool
x /= y = not (x == y)
instance Eq Bool where
True == True = True
False == False = True
_ == _ = False
-- the (/=) operator is automatically derived
instance Eq () where
() /= () = False
-- the (==) operator is automatically derived
It is indeed common to have default self-referring implementations which evaluate to bottom unless something is redefined in the instances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With