Reputation: 23135
I've written what I imagine would be a common function in Haskell, but I couldn't find it implemented anywhere. For want of a better word I've called it "transform".
What "transform" does three arguments: a list, and an initial state and a function that takes an element from the list, a state, and produces an element for an output list, and a new state. The output list is the same length as the input list.
It's kind of like "scanl" if it also took a state parameter, or like "unfoldr" if you could feed it a list.
Indeed, I've implemented this function below, in two different ways that have the same result:
transform1 :: (b -> c -> (a, c)) -> c -> [b] -> [a]
transform1 f init x = unfoldr f' (x, init)
where
f' ((l:ls), accum) = let (r, new_accum) = f l accum in Just (r, (ls, new_accum))
f' ([], _) = Nothing
transform2 :: (b -> c -> (a, c)) -> c -> [b] -> [a]
transform2 f init x = map fst $ tail $ scanl f' init' x where
f' (_,x) y = f y x
init' = (undefined, init)
This sort of operation seems relatively common though, that is, taking a list and walking through it with some state and producing a new list, so I'm wondering if there's a function that already exists and I'm reinventing the wheel. If so, I'll just use that, but if not, I might package what I've got into a (very) small library.
Upvotes: 4
Views: 692
Reputation: 18189
This is almost, but not exactly Data.List.mapAccumL
. The difference is that mapAccumL
also includes the final state. Also it recently got generalized to Traversable
.
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
Upvotes: 6