I am new to Haskell. I wrote my own monad which is the State monad with error handling:
newtype MyMonad a = MyMonad (State -> Either MyError (State, a))
I use it in an interpreter of a small language. Now I want to add some IO operations to my language (reading/writing), but I don't know how to enclose IO monad inside mine. I know I could combine ErrorT, StateT, IO and achieve this result but is there other way to do it without them?
You can look at how StateT is implemented:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
To combine state with IO
you just put IO
in place of m
and get the desired type: s -> IO (a,s)
.
If you have errors too, this becomes something like s -> IO (Either e (a, s))
or s -> IO (Either e a, s)
depending on whether you want the failed computations to affect state.
Note that you can't make s -> Either e (IO (a, s))
a monad without a time machine.
Update
It turns out you can't make it a monad even with time machine.
To show why it is impossible, let us simplify our monad by using ()
instead of s
first: data M e a = M { runM :: Either e (IO a) }
Now, imagine the following program:
unsafePerformIO :: IO a -> a
unsafePerformIO io = fromLeft $ runM $ do
a <- M $ Right $ io
M $ Left a
Obviously, this function is impossible and thus the monad instance for M
is impossible too.
What time machine could give you is the ability to treat IO
exactly like one treats State
. However, I didn't realise that Either e (s -> (a, s))
is not a monad.
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