To map or not to map, that is the question.
Better not to map.
Why? Because map id == id
anyway, and you only want to map through one element, the first one found to be equal to the argument given.
Thus, split the list in two, change the found element, and glue them all back together. Simple.
See: span :: (a -> Bool) -> [a] -> ([a], [a])
.
Write: revappend (xs :: [a]) (ys :: [a])
== append (reverse xs) ys
, only efficient.
Or fuse all the pieces together into one function. You can code it directly with manual recursion, or using foldr
. Remember,
map f xs = foldr (\x r -> f x : r) [] xs
takeWhile p xs = foldr (\x r -> if p x then x : r else []) [] xs
takeUntil p xs = foldr (\x r -> if p x then [x] else x : r) [] xs
filter p xs = foldr (\x r -> if p x then x : r else r) [] xs
duplicate xs = foldr (\x r -> x : x : r) [] xs
mapFirstThat p f xs = -- ... your function
etc. Although, foldr
won't be a direct fit, as you need the combining function of the (\x xs r -> ...)
variety. That is known as paramorphism, and can be faked by feeding tails xs
to the foldr
, instead.