I've started to learn Haskell and feeling overwhelmed with it. I'm now trying to create a function that either returns a string from standard input or from the contents of a list of files. In other words, I'm trying to replicate the behavior of Unix wc utility which takes input from stdin when no files are given.
I've created something like this:
parseArgs [] = [getContents]
parseArgs fs = mapM readFile fs
But it doesn't compile since in one case I have [IO String] and in the other IO [String]. I can't make this pattern matching to return IO [String] in all cases. Please point me to right direction.
IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.
An IO String is a String in the IO-Monad. If a function in the IO-Monad returns an IO String, you get the String by doing: do str <- ioFunc. A function is in the IO-Monad when it needs IO-access and has to return IO types.
In Haskell a String is just a list of Char s, indeed type String = [Char] . String is just an "alias" for such list. So all functions you define on lists work on strings, given the elements of that list are Char s.
The print function outputs a value of any printable type to the standard output device.
To make the first pattern also IO [String]
, you have to unpack the value from inside the list first and then repack it. Something like this:
do c <- getContents
return [c]
In normal monadic notation:
getContents >>= \c -> return [c]
In a case like this, it's usually better to use a functor instead of a monad. Then you can avoid the return
:
fmap (:[]) getContents
(:[])
has the same meaning as \x -> [x]
, it creates a singleton list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With