开发者

Haskell : not getting this with IO [FilePath]

Working through tutorials etc. in ghci - so far so good. I'm so completely missing something though : my function builds an IO [FilePath] "thing". In ghci it comes out like this:

["xml","velocity.log.1","velocity.log"] (list truncated fo开发者_StackOverflow社区r brevity)

I see that the function is doing what I want. Next step is I want to "print" that out myself.

Nothing I do lets me print the result. I don't want to perpetuate my Java/C#/Python habits in Haskell - no point in that. I believe there's a good reason for Haskell doing things differently, but I can't see how to get the (limited) value out of this function.

module Main (
    main
) where

import RecursiveContents

main = do putStrLn "this"
          getRecursiveContents "/home/xyz/myDir"

This works. But what if I want main to print the result of getRecursiveContents "/home/xyz/myDir" ?

In ghci I can just type/paste getRecursiveContents "/home/xyz/myDir" and the stuff spews out - what do I have to do to print it myself?

If I do :

let xyz = getRecursiveContents "/home/xyz/myDir" in ghci, the only thing I can do with xyz is type: xyz <enter> and see the result.

I cannot do head, tail, etc. etc.. I know that IO [FilePath] is something special and not a the same as array or list [a] - but nothing I do is helping me to understand getting past this.

I must be missing something - something I can't find in Learn You a Haskell, or Real World Haskell. Am I not rtfm-ing in the right place?

Any feedback or dope-slaps appreciated.


To get the results of an IO action (i.e. to run the action) you bind the results of the IO computation to a variable:

Assuming:

getRecursiveContents :: FilePath -> IO String

Then you can just print the result:

main = do str <- getRecursiveContents "/home/xyz/myDir"
          print str

Obviously this is just an example, but when the function really is just two lines people don't usually use do notation and avoid explicitly naming the intermediate variable of str:

main = getRecursiveContents "/home/xyz/myDir" >>= print


Use <- in the do-notation to get to the [FilePath]. You can then manipulate it with any list functions, as long as you end up with some IO action.

main = do putStrLn "this"
          contents <- getRecursiveContents "/home/xyz/myDir"
          print contents

Alternatively, you can use >>= to feed the output of one IO action into another. It's the same thing, just written differently.

main = do putStrLn "this"
          getRecursiveContents "/home/xyz/myDir" >>= print

For a more thorough explanation, see the I/O chapters of

  • Learn You a Haskell
  • Real World Haskell

The reason why it works in GHCi, is that when GHCi has evaluated your expression, it looks at the type. If it's IO a, it will run the action and display the result automatically, while in a real program you have to do this yourself. See the GHC user's guide.


You can bind values in do blocks. This is also the place where you can apply pure functions (like show, tail and so on):

main = do putStrLn "this"
          x <- getRecursiveContents "/home/xyz/myDir"
          putStrLn (show x)

If the foo is of type IO a then you need something like do and x <- foo to get the value.

Consult any monad tutorial for more info.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜