# [Haskell-cafe] Converting IO [XmlTree] to [XmlTree]

Jake McArthur jake.mcarthur at gmail.com
Tue Apr 14 12:11:50 EDT 2009

```rodrigo.bonifacio wrote:
> I guess this is a very simple question. How can I convert IO [XmlTree]
> to just a list of XmlTree?

You can't, unless you use `unsafePeformIO`, as others have already
pointed out. Yet others have, more "correctly," suggested that you use
do notation to bind a variable with the type you expect. I want to go
into a little more detail .I have a spontaneous Monad tutorial to throw
out, I guess.

How you can convert a value of type `IO [XmlTree]` is probably the wrong
question. The right question is how you can convert a function of type
`[XmlTree] -> A` into a function of type `IO [XmlTree] -> IO A`. The

fmap, liftA, liftM, (<\$>) :: Monad m => (a -> b) -> (m a -> m b)

I will use `fmap` to mean any of the above names. In your case, applying
fmap to a function foo:

foo      ::    [XmlTree] ->    A
fmap foo :: IO [XmlTree] -> IO A

So any time you need to pass an IO value to a pure function, this is one
way to do it.

Suppose that the function actually returns an IO value, though. Here, we
will call the function `bar`:

bar      ::    [XmlTree] ->     IO A
fmap bar :: IO [XmlTree] -> IO (IO A)

Now we seem to be in a similar situation as before. We have an extra IO
that we don't want. There is a function for this:

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

So, we can use `join` to transform an expression of type `IO (IO a)` to
an expression of type `IO a`. Putting it all together:

bar             ::    [XmlTree] ->     IO A
fmap bar        :: IO [XmlTree] -> IO (IO A)
join . fmap bar :: IO [XmlTree] ->     IO A

And we now have a sensible function again.

Of course, this is a common pattern, using `join` and `fmap` together,
so we have yet another function:

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

(Note that this has a different argument order than (>>=). I prefer this
form since it emphasizes that it actually transforms a function.)

So, now we have

bar       ::    [XmlTree] -> IO A
(bar =<<) :: IO [XmlTree] -> IO A

Putting it all together, with a function that gives us the `IO [XmlTree]`:

xmlTree         :: IO [XmlTree]
bar             ::    [XmlTree] -> IO A
bar =<< XmlTree ::                 IO A

And that last line is equivalent to this in do notation:

do tree <- xmlTree
bar tree

If you have any questions, please do ask. I understand that it can
appear quite dense to a beginner. I'm thinking about using this approach
in a blog article, which would have more detail and examples, but I
would like to be aware of potential stumbling blocks.

- Jake
```