1

I am trying to create a function without parameters that create a list comprehension. When I try to run the code, I get a parse error and it fails to compile and I have no idea why.

I keep trying to run it on the terminal but it won't work.

This is my code:

outfits = let pants = ["jeans", "khaki", "leggings"]
              shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
              shoes = ["brogues", "converse", "sandals", "adidas"]

outfits1 = [ (x, y, z) | z <- pants, y <- shirts, x <- shoes ]

This is the error that comes up:

warmup.hs:7:11: error: parse error on input ‘outfits1’
  |
7 |           outfits1 = [ (x, y, z) | z <- pants, y <- shirts, x <- shoes ]
  |           ^^^^^^^^
2
  • 12
    Where is the in accompanying the let? Commented Apr 19, 2019 at 18:35
  • 5
    There's no such thing as a function without parameters. outfits1 is just a list. Commented Apr 19, 2019 at 18:43

1 Answer 1

6

Without the let expression, you would simply write

outfits = [ (x, y, z) | z <- ["jeans", "khaki", "leggings"], y <- ["white shirt", "grey turtleneck", "pink polo", "green hoodie"], x <- ["brogues", "converse", "sandals", "adidas"] ]

A let expression requires two parts: the local bindings immediately following the keyword let, and the expression which uses those bindings, following the keyword in:

outfits = let pants = ["jeans", "khaki", "leggings"]
              shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
              shoes = ["brogues", "converse", "sandals", "adidas"]
          in [ (x, y, z) | z <- pants, y <- shirts, x <- shoes ]

Alternately, you can write this using a where clause, which puts the "main" expression first:

outfits = [ (x, y, z) | z <- pants, y <- shirts, x <- shoes ]
              where pants = ["jeans", "khaki", "leggings"]
                    shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
                    shoes = ["brogues", "converse", "sandals", "adidas"]

Applicative instead of list comprehension

I would write this using the Applicative instance for lists instead, using the 3-tuple constructor (,,), which lets you do away with boilerplate variables x, y, and z.

outfits = (,,) <$> ["jeans", "khaki", "leggings"]
               <*> ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
               <*> ["brogues", "converse", "sandals", "adidas"]

You can still use either a let expression or a where clause to provide names for each component of an outfit:

outfits = let pants = ["jeans", "khaki", "leggings"]
              shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
              shoes = ["brogues", "converse", "sandals", "adidas"]
          in (,,) <$> pants <*> shirts <*> shoes

or

outfits = (,,) <$> pants <*> shirts <*> shoes
              where pants = ["jeans", "khaki", "leggings"]
                    shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
                    shoes = ["brogues", "converse", "sandals", "adidas"]

If ... <$> ... <*> ... <*> ... looks too esoteric, you can give the pattern a more descriptive name:

outfits = mixAndMatch pants shirts shoes
           where pants = ["jeans", "khaki", "leggings"]
                 shirts = ["white shirt", "grey turtleneck", "pink polo", "green hoodie"]
                 shoes = ["brogues", "converse", "sandals", "adidas"]
                 mixAndMatch a b c = (,,) <$> a <*> b <*> c
Sign up to request clarification or add additional context in comments.

3 Comments

mixAndMatch = liftA3 (,,), which might be more palatable to inline even if you don't like applicative style.
or just zip3. Jumping into applicative for someone who's still learning the syntax might be a bit much.
@rampion zip3 doesn't compute a cross product of the three lists.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.