我已经写过我想象的在Haskell中的常见功能,但我无法在任何地方找到它。因为缺少一个更好的词,我称之为"转换"。
什么"转换"有三个参数:一个列表,一个初始状态和一个从列表中获取元素的函数,一个状态,并为输出列表生成一个元素,以及一个新状态。输出列表与输入列表的长度相同。
有点像" scanl"如果它也采用了状态参数,或者喜欢"展开"如果你可以给它一个列表。
事实上,我已经在下面以两种不同的方式实现了这个功能:
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)
这种操作似乎比较常见,也就是说,拿一个列表并用一些状态遍历它并生成一个新列表,所以我想知道是否存在已经存在的功能而且我和#39;重新发明轮子。如果是这样,我只会使用它,但如果没有,我可能将我所拥有的内容打包到一个(非常)小的库中。
答案 0 :(得分:6)
这几乎是,{但不完全是Data.List.mapAccumL
。区别在于mapAccumL
还包括最终状态。最近它也被推广到Traversable
。
mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)