How can I use pure functions inside IO functions? :-/
For example: I'm reading a file (IO function) and I want to parse its context, a string, by using a pure function with referential transparency.
It seems such worlds, pure functions and IO functions, are separated. How can I possibly bridge them?
Alex Horsman helped me. He said:
"Perhaps I'm misunderstanding, but that sounds pretty simple? do {x <- ioFunc; return (pureFunc x)}"
And then I solved my problem:
The simplest way is to use
fmap
, which has the following type:IO
implementsFunctor
, which means that we can specialize the above type by substitutingIO
forf
to get:In other words, we take some function that converts
a
s tob
s, and use that to change the result of anIO
action. For example:What just happened there? Well,
map toUpper
has type:It takes a
String
as an argument, and returns aString
as a result. Specifically, it uppercases the entire string.Now, let's look at the type of
fmap (map toUpper)
:We've upgraded our function to work on
IO
values. It transforms the result of anIO
action to return an upper-cased string.We can also implement this using
do
notation, to:It turns out that every monad has the following property:
In other words, if any type implements
Monad
, then it should always be able to implementFunctor
, too, using the above definition. In fact, we can always use theliftM
as the default implementation offmap
:liftM
is identical tofmap
, except specialized to monads, which are not as general as functors.So if you want to transform the result of an
IO
action, you can either use:fmap
,liftM
, ordo
notationIt's really up to you which one you prefer. I personally recommend
fmap
.You can also consider liftM function from Control.Monad.
A little example to help you (run it into ghci as you are under the IO Monad)
The actual answer is as follows:
return
wraps it in the appropriate monad so thatdo
can assign it toval
.