Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell left arrow operator alternative

Tags:

haskell

monads

I'm new to haskell and functional programming in general and I have a problem with monads. Let's say I have got a list of filenames:

-- do block --
let filenames = ["file1","file2"]

and I want to generate a list of those files' content, using list comprehensions:

let content = [str <- readFile f | f <- filenames]

Ofc, this kind of usage is not valid. As I understand this kind of "assignment" can be used in do block, when "chaining" the result with the next instruction.

Is there maybe an alternative way to use the left arrow (or >>=) operator. I imagine sth like this:

let content = [leftArrAlter $ readFile f | f <- filenames]
like image 367
ziyiyituxe Avatar asked Feb 25 '26 07:02

ziyiyituxe


1 Answers

Let's start with the simpler list

let content = [readFile f | f <- filenames]

content has type [IO String]; it's a list of IO actions, each of which can produce a String when executed.

What you would like is something of type IO [String]: a single IO action that, when executed, gives you a list of String values.

That's where the sequence function comes in. In this case, we only need to consider the specialized version that has type [IO String] -> IO [String]:

content <- sequence [readFile f | f <- filenames]

We can also use traverse, in particular the specialized version with type (FilePath -> IO String) -> [FilePath] -> IO [String]:

content <- traverse readFile fileNames

For reference, the general types of the two functions:

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

We used [] as our Traversable, and IO as our Monad/Applicative.

like image 107
chepner Avatar answered Feb 28 '26 04:02

chepner