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.
精彩评论