misterMonkeyMan
misterMonkeyMan

Reputation: 1

Implementation of MonadState without using return?

For a practical assignment I have to implement MonadSate in Haskell, without using the return function, and by defining get and put in terms of modify, and modify in terms of get and put.

     class Monad m ⇒ MonadState m s | m → s where
     get :: m s
     put :: s → m ()
     modify :: (s → s) → m s

I got these laws that I can use:

put s1 >> put s2 ≡ put s2
put s >> get ≡ put s >> return s
get >>= put ≡ return ()
get >>= (λs → get >>= k s) ≡ get >>= (λs → k s s)

I tried the following:

     class (Monad m) => MonadState m s | m -> s where
       get :: m s
       get = modify (\s -> s)

       put :: s -> m ()
       put s = modify (\_ -> s) >> return ()

       modify :: (s -> s) -> m s
       modify f = do
         s <- get
         put (f s) >> get

But I am using return (), which is not allowed

I do not understand how when replacing the old state with the new one, I can return an empty tuple, when the result-type of modify is m s, and not m ()

Upvotes: 0

Views: 101

Answers (1)

Mokosha
Mokosha

Reputation: 2822

Piggy-backing on the comment from Fyodor: to distill your problem, you have a value of type m s and you want a value of type m (). So what you're looking for is some function f :: m s -> m (). There are a number of ways to implement this function.

One way, which you already discovered, is to use return ():

f :: (Monad m) => m a -> m ()
f = (>> return ())

Another way, is simply to use the properties of Monad, which is a subclass of Functor. As a reminder, fmap has the signature fmap :: (a -> b) -> f a -> f b. So, you'd need some function g :: a -> () such that

f :: (Monad m) => m a -> m ()
f = fmap g

There is only one such implementation of g.


As an added exercise, it's useful to think about what the semantics are when using (>>) versus fmap in this exercise.

Upvotes: 2

Related Questions