0

Why use list comprehension instead of more functional approach like - map (*2) [1..5](just one example)?

I think list comprehension syntax is not very straight forward, needs remembering, and is redundant syntax and feature in haskell because you can do everything it can do with just list functions.

Am I incorrect. Is there something you can do with list comprehension that you cannot with functional approach?

Piliponful
  • 142
  • 3
  • 10
  • 1
    Deleted my comment; somehow, I though this was tagged [python]. – chepner Mar 11 '23 at 13:46
  • 3
    Sometimes list comprehensions don't make the code more readable. Indeed, `[x*2 | x<-[1..5]]` is not that better than your map. Some other times, at least in my eye, they do: `[x | Left x <- ys]` is less convenient to write without list comprehensions. Another example: `[ (x,y) | (x:xs) <- tails ys, y <- xs ]` generates all the pairs of elements `x,y` inside `ys` where `x` occurs earlier than `y`. If you are a beginner and don't like them, feel free to ignore them. Coding without them can lead to good learning exercises. – chi Mar 11 '23 at 14:16

1 Answers1

8

You're not wrong, list comprehension syntax isn't needed. But neither is do notation (which BTW desugars in almost the same way), or simple list literals, or even string literals. Instead of writing "Hello, World!" you could always write

       'H':'e':'l':'l':'o':',':' ':'W':'o':'r':'l':'d':'!':[]

Going a step further you could also ask why we don't just write programs in lambda calculus / System F, instead of an actual programming language.

You can probably see where I'm getting with this:

Why would you ever use list comprehension

– because they're concise, nice-looking and it's easily understandable what's meant.

Specifically, I think list comprehensions nicely put the information that's most useful for quick understanding up-front: for example, [x*2 | x<-[1..5]] is parsed by the eye in something like

  • [... ok, there's a list coming up
  • [x*2 ... ok, at least one entry has the form x*2 (whatever x is), i.e. an even number.
  • [x*2 |... ah, all entries are even numbers, quantized over some source
  • [x*2 | x<-... ok, so x is what changes for each entry of the list
  • [x*2 | x<-[1..5] right, so the specific numbers used will be [1..5]

This is, I'd say, indeed in quite many situations roughly the order from most- to least interesting for a quick read. It basically starts by explaining by example (or, prototype) what kind of result entries you get, before getting into the details of how the entries differ.

The extreme opposite is the imperative-style

forM [1..5] $ \x -> do
   return $ x*2

Here, we begin with "start a loop" and "loop over those numbers", which is nice in the sense that it gives an overview about what's about to happen operatively, but little insight regarding the denotational meaning of the result. It then goes on to define the variable x, etc..

The map version is somewhere in between, with the extra quirk of using point-free syntax. Which has its own advantages and disadvantages.

All three styles have their use cases, it's up to judgement which one works best in each situation.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • got you, that what I thought. I think for myself I will not use them. But my main question was to understand if you can do something with list comprehension that you cannot with just list functions(because I don't have much experience with haskell yet). From your answer I see that they are just for convince. Thank you for the answrer. – Piliponful Mar 11 '23 at 13:53
  • 2
    To add to this fine answer, here's an example where list comprehension is (IMO) more readable than the more 'standard' combinators: https://stackoverflow.com/a/74704538/126014 – Mark Seemann Mar 11 '23 at 14:02
  • 2
    @Piliponful No, list comprehensions are synctatic sugar. They don't provide anything you can't already do without. They can always be transformed into code exploiting standard functions like `concatMap` and little else. Their semantics is given in the Haskell Report though [such a code transformation](https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-420003.11). – chi Mar 11 '23 at 14:02