Sawyer
Sawyer

Reputation: 15917

get put and state in MonadState

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

Upvotes: 5

Views: 614

Answers (1)

chi
chi

Reputation: 116174

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.

Upvotes: 6

Related Questions