Reputation: 11
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 ]
| ^^^^^^^^
Upvotes: 1
Views: 69
Reputation: 531758
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 comprehensionI 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
Upvotes: 6