[Haskell-beginners] Get things from IO monad

Ertugrul Soeylemez es at ertes.de
Fri May 6 11:41:38 CEST 2011


jianqiuchi at gmail.com wrote:

> I just want to get something from IO monad and wrap it with some other
> monad. Is there anyway to do that? Thanks.

You've got quite a "just" there.  This is conceptually impossible,
because it does not make sense.  There is no "some other monad", because
every monad has a precise, significant meaning and in general you cannot
just cast values from one type to another.  If conversion is possible,
there needs to be a specific conversion function, called a natural
transformation, which knows the semantics of both monads.  For all 'a'
and 'm', it is in general possible to convert values of type 'IO a' to
'MonadIO m => m a'.  The natural transformation for that is called
liftIO.

What you can try to do is to find a transforming variant of whatever
monad you are working in.  So instead of MyMonad use MyMonadT IO.

It is a common wrong interpretation that you want to "get out of" the IO
monad, what technically means:  You want to convert IO Something to just
Something.  There is indeed a combinator for accessing that Something,
but it has not the type you would expect.  It's called (>>=) and has the
following type signature:

  (>>=) :: Monad m => m a -> (a -> m b) -> m b

In this case:

  (>>=) :: IO a -> (a -> IO b) -> IO b

Just look at the type and think about how you can use this function to
do what you want.  It converts your IO Something to the Something, which
you want, but only for a certain function, which is its second argument.

Why do people want to get out of the IO monad?  Because they interpret
the arrow as "going to", and there is a general 'a -> IO a' function
(called 'return'), but not an 'IO a -> a' function.  A function of this
type cannot exist (or it can, but it cannot do anything useful,
particularly not what you want).  But it's also not needed, because you
have (>>=), which is consistent with Haskell's type system and the
semantics of IO.

Less relevantly, let me also support what Felipe said.  Aditya Siram's
statement is very misleading, because it suggests that using
unsafePerformIO is fine, if you don't overuse it.  Wrong!  Using it to
cast between types is *wrong* and *will* get you into trouble (in this
case you are casting from IO Something to Something).  Do not use any of
the "unsafe" functions, until you understand why you do *not* need them.
At that point you may start using them.  I'm programming in Haskell for
a few years now, and I have used unsafePerformIO exactly once.


Greets,
Ertugrul


-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://ertes.de/





More information about the Beginners mailing list