Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a Haskell function that turns IO String into IO [String]?

Tags:

io

haskell

monads

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.

like image 803
Valentin V Avatar asked Mar 08 '11 17:03

Valentin V


People also ask

What is IO () Haskell?

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.

What is an IO String?

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.

How do you define a String in Haskell?

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.

Which function is used for output in Haskell?

The print function outputs a value of any printable type to the standard output device.


1 Answers

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.

like image 109
fuz Avatar answered Sep 20 '22 15:09

fuz