Reputation: 1
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
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