Map over list, except for last list element
Just re-write map
but make a special case when there's only one element:
mapBut1 :: (a -> a) -> [a] -> [a]
mapBut1 f [] = []
mapBut1 f [x] = [x]
mapBut1 f (x:xs) = f x : mapBut1 f xs
This will now work even for infinite lists, it's a lot faster than calculating the length, and makes it more readable. Note that this does restrict your function to be of type a -> a
instead of a -> b
.
Alternatively, you could do
mapBut1 f (x:y:xs) = f x : mapBut1 f (y:xs)
mapBut1 f other = other
They're equivalent definitions, but the latter uses 1 fewer pattern matches. I would prefer the former, though, since it's more immediately obvious what cases are being handled.
This is a job for pretend-paramorphism, as usual:
import Data.List (tails)
mapButLast :: (a -> a) -> [a] -> [a]
mapButLast f = foldr g [] . tails where
g (x:_:_) r = f x : r
g xs _ = xs
Or with proper para
we'd just write
mapButLast f = para g [] where
g x [] r = [x]
g x _ r = f x : r
where
para f z (x:xs) = f x xs (para f z xs)
para f z [] = z
You can also use init
and last
from standard librairies (no special import) if you don't care about performances.
you can write
map f (init list) ++ [last list]
where
f
: function you want to maplist
: list you want to map over