Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add IO to my own monad in Haskell?

Tags:

haskell

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?

like image 913
Camille Avatar asked Sep 16 '11 09:09

Camille


1 Answers

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.

like image 73
Rotsor Avatar answered Nov 15 '22 12:11

Rotsor