5

Possible Duplicate:
A Haskell function of type: IO String-> String

i'm reading some data from a file using the readFile function available in Haskell. But this function returns me some data stored as IO String. Does anybody knows how do I convert this data into a String type (or any function that reads String from a file, without the IO () type)?

Community
  • 1
  • 1
user1050519
  • 51
  • 1
  • 2
  • While this is definitely a duplicate, I have to wonder.. What makes people think there's such a thing as a function that makes an action that does IO to get a string not do IO? – Carl Nov 17 '11 at 01:03
  • It is a general misconception of side effects. – nponeccop Nov 17 '11 at 15:08
  • I think it has less to do with side effects than it does that almost everyone uses monads before they understand them. – amindfv Nov 19 '11 at 01:15

2 Answers2

19

It is a very general question about extracting data from monadic values.

The general idea is to use >>= function:

main = readFile foo >>= \s -> print s

>>= takes 2 arguments. It extracts the value from its first argument and passes it to its second argument. The first argument is monadic value, in this case of type IO String, and the second argument is a function that accepts a plain, non-monadic value, in this case String.

There is a special syntax for this pattern:

main = do
   s <- readFile foo
   print s

But the meaning is the same as above. The do notation is more convenient for beginners and for certain complicated cases, but explicit application of >>= can lead to a shorter code. For example, this code can be written as just

main = readFile foo >>= print

Also there are a big family of library functions to convert between monadic and non-monadic values. The most important of them are return, fmap, liftM2 and >=>.

The concept of monad is very useful beyond representing IO in a referentially transparent way: these helpers are very useful for error handling, dealing with implicit state and other applications of monads.

The second most important monad is Maybe.

nponeccop
  • 13,527
  • 1
  • 44
  • 106
  • `most of the time the explicit application of >>= leads to a better code` - i wonder how you could substantiate this claim. Nevertheless, +1 for good explanation. – Ingo Nov 22 '11 at 16:36
  • "most of the time" and "better" are stop words. Thank you for spotting them. Fixed. – nponeccop Nov 22 '11 at 17:13
2

I'd treat the IO type as a functor in this case, and instead of getting the value out of it, I'd send my function inside it and let the Functor instance deal with creating a new IO container with the result from my function.

> :m +Data.Functor
> length <$> readFile "file.txt"
525

<$> is an alias for fmap. I like <$> more, but it's just a personal preference.

Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • 3
    That's not a wrong answer, however when someone is starting to _trying_ to understand the concept of monadic values, you can't throw *Applicative Functors* to them without getting them even more confused. – Roman Gonzalez Nov 16 '11 at 22:04
  • @RomanGonzalez true, but I'm not sure he can get a good grasp of this without being confused in the beginning. And I don't want to write a course either. Not here/now at least. Small correction, what I've used is just a functor, not an applicative functor. The module name is misleading indeed. Maybe I should have used `Data.Functor`... Oh, and I think that `Functor` should be thought before `Monad`. It makes more sense. – Ionuț G. Stan Nov 16 '11 at 22:19