Clinton
Clinton

Reputation: 23135

Haskell "transform" function

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

Answers (1)

Ørjan Johansen
Ørjan Johansen

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

Related Questions