Mampenda
Mampenda

Reputation: 671

How to use map instead of list comprehension (Haskell)

I have made this code which replaces all elements from a list which fulfilss a predicate:

gRep :: (t -> Bool) -> t -> [t] -> [t]
gRep pred x ys = [if pred y then x else y | y <- ys]

so f.eks I get these outputs:

ghci> gRep (<'g') 'z' "abcdefghijklmnopqrstuvwxyz"
"zzzzzzghijklmnopqrstuvwxyz"
ghci> gRep (<3) 0 [1,2,3,4,5,6,7,8,9]
[0,0,3,4,5,6,7,8,9]

How can I write this function using map instead?

I tried to write it like this:

gRepMap :: (t -> Bool) -> t -> [t] -> [t]
gRepMap pred x ys = map (\zs -> if (pred y) then x else y | y <- ys) ys

But I get a parser-error because of | y <- ys . I know this may be a possible duplicate, but I couldnt find a question which dealt with this particular conversion.

Upvotes: 1

Views: 189

Answers (2)

Will Ness
Will Ness

Reputation: 71075

gRep    pred x ys = [           if (pred y) then x else y | y <- ys]
--                                                         ^^^ ------>>>--.
gRepMap pred x ys = map (\ y -> if (pred y) then x else y )      ys   --  |
                          ^^^ <----------<<<--------------<<<-------------*

That's how it works for any expression in the output section of list comprehension, according to the Haskell Report, which gives an equivalent translation,

 [ exp |     y <-        ys ]
===
 concatMap (\y -> [exp]) ys
===
 map       (\y ->  exp ) ys

The Report gives a more general translation which is equivalent to the above in the case of irrefutable pattern, like y is here.

The | y <- ys bit belongs to the list comprehension syntax, you shouldn't have copied it there. Instead, y becomes the lambda parameter, and ys is the list being mapped over.

Upvotes: 2

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

The variable in the lamba expession \zs -> … is zs this variable will ues the elements in the list, since the lambda expression is called with each element of th elist, as a result you thus perform the mapping with:

gRepMap :: (t -> Bool) -> t -> [t] -> [t]
gRepMap pred x ys = map (\zs -> if pred zs then x else zs) ys

Usually in Haskell a variable name ends with an s to denote a collection of items (especially when working with lists). Here zs is an element of that list, it thus makes more sense to name the variable y or z, not zs:

gRepMap :: (t -> Bool) -> t -> [t] -> [t]
gRepMap pred x ys = map (\y -> if pred y then x else y) ys

Upvotes: 3

Related Questions