3

In a Haskell project I'm given to debug, there are instances in the code where map is used with only one parameter - a list - is passed.

For example

printReports :: [Report] -> IO ()
printReports = putStrLn . unlines . map show

and

printRuns' :: [Run] -> IO ()
printRuns' = putStrLn . unlines . map showRecipes'

What does map mean/do in this context?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
CodyBugstein
  • 21,984
  • 61
  • 207
  • 363
  • 1
    http://www.haskell.org/haskellwiki/Partial_application – Cat Plus Plus Feb 14 '13 at 16:50
  • 2
    Also the applied argument is a function, not a list. `map` is `(a -> b) -> [a] -> [b]` which is the same as `(a -> b) -> ([a] -> [b])`. – Cat Plus Plus Feb 14 '13 at 16:51
  • 1
    You can read `f . g . h` as a "pipe", which takes data and passes it through `h`, then `g`, then `f`. `map show` is one of the functions in the pipe (it takes a list and converts every element of the list to a stream) – luqui Feb 15 '13 at 10:02

4 Answers4

10

Type of map:

map :: (a -> b) -> [a] -> [b]

So you have to provide a function from a to b and a list of type a.

In your examples, the function is already given (show and showRecipes'), and therefore, you only have to provide for printReports and printRuns' a list.

What happened there is called partially applied function, see here http://www.haskell.org/haskellwiki/Partial_application

kaan
  • 796
  • 2
  • 6
  • 20
10

As others have said, map show is a partially applied function, and reading up on that is a good idea. But the code you've given is also an example of the point-free style of programming, and it may be easier for you to understand it as such. The function printReports could also have been written as

printReports xs = (putStrLn . unlines . map show) xs

or, equivalently,

printReports xs = putStrLn . unlines . map show $ xs

Generally speaking, all of the following are equivalent:

myFunction x y z = someExpression x y z
myFunction x y = someExpression x y
myFunction x = someExpression x
myFunction = someExpression

That's a slight oversimplification, but it will get you started.

mhwombat
  • 8,026
  • 28
  • 53
  • 6
    They're equivalent in that they all give the same result. They may differ in performance in some situations, and the Dreaded Monomorphism Restriction may cause problems if there's no type signature. But they're equivalent in the most important ways. – C. A. McCann Feb 14 '13 at 17:24
3

As a rule of thumb, if you have something like this...

foo = bar . foobar . blafasel

... you can mentally substitute the dots by $ and add a variable on both sides

foo x = bar $ foobar $ blafasel x

Why this works is already explained in the other answers, but this trick helps me to read point-free style without much thinking.

Landei
  • 54,104
  • 13
  • 100
  • 195
2

In this context map apply the show function to each Report present in the list. The result should look like [show report0, show report1,... ,show reportn]

Say differently you pass a list of report and the function map, map for each item of type of report in the list the show function.

The way yours function are built correspond to the point free style.

zurgl
  • 1,930
  • 1
  • 14
  • 20