I have defined in Haskell a custom monad combining state and error processing like this:
import Control.Applicative
import Control.Monad
data Result a e = Ok a | Error e
newtype StateError s e a = StateError { runStateError :: s -> (Result a e, s) }
instance Functor (StateError s e) where
fmap f m = StateError $
\s -> case runStateError m s of
(Ok x, s1) -> (Ok (f x), s1)
(Error e, s1) -> (Error e, s1)
instance Applicative (StateError s e) where
pure x = StateError $ \s -> (Ok x, s)
a <*> b = ap a b
instance Monad (StateError s e) where
return = pure
m >>= f = StateError $
\s -> case runStateError m s of
(Ok x, s1) -> runStateError (f x) s1
(Error e, s1) -> (Error e, s1)
get = StateError $ \s -> ((Ok s), s)
put s = StateError $ \_ -> ((Ok ()), s)
main = return ()
The code compiles fine, but it seems there is some redundancy here between the definitions of fmap
and the >>=
bind operator in the monad.
How can I redefine the bind operator to leverage the functor definition?
If this is not possible, why am I forced to define a functor for my custom monad?
It seems useless if I am not going to use fmap
anywhere.
Thanks
NOTE: I know monad transformers exist, and perhaps they are the right way to combine the existing state and error monads into one, but I preferred this route for learning reasons (I have little experience with monads).
NOTE: This question is a follow-up of my other question How to create a monad that combines state and error in Haskell.