Search code examples
haskellhaskell-turtle

Turtle: how to read a list of files?


Assume we have a file my_file.txt with contents:

foo
bar

and another file my_other_file.txt containing:

baz

I would like to read the contents of these two files using turtle so that I get a Shell of lines which will produce:

foo
bar
baz

In Haskell's turtle library one can read a list of files by using input, for instance:

view $ input "my_file.txt"

We have that

input :: FilePath -> Shell Line

And Shell has no Monoid instances (which I think makes sense since we cannot associate IO operations), so the only operator I can think of using is (<|>):

view $ foldl (<|>) empty $ map input ["my_file.txt", "my_other_file.txt"]

While this produces the desired effect, I wonder whether there is a library in the turtle eco-system that takes care of this, or whether there is a traverse like operation that can be use on Alternative's.

EDIT: the effect above could be also achieved by using asum:

asum $ input <$> ["my_file.txt", "my_other_file.txt"]

Solution

  • Line has a Monoid instance. If we have a list of Lines, we can mconcat them into a single one:

    do
      exampleA <- input "my_file.txt"
      exampleB <- input "my_other_file.txt"
      return $ mconcat [exampleA, exampleB]
    

    Since Shell has an Applicative instance, we can use traverse to use input over a list of files:

    traverse input ["my_file.txt","my_other_file.txt"]
    

    We end up with a Shell [Line]. Since Shell is a Functor, we can fmap mconcat (or fold if you don't use a list):

    mconcat <$> traverse input ["my_file.txt","my_other_file.txt"]