我正在尝试编写一种类似scanl函数的扫描:
general_scanl' :: (a->b->a)->(a->b->[c])->a->[b]->[c]
该函数用于输出与以下两个怪物相同的内容:
general_scanl' f g x y = snd $ foldl' (\(p,q) r -> (f p r,q ++ g p r)) (x,[]) y
,或者
general_scanl' f g x y = concat $ zipWith g (scanl f x y) y
第一个定义的缺点是它包含一个手写的lambda 第二个定义的缺点是它累积了一个列表列表(scanl f x y),这是不必要的......
我的问题:有更简洁的方法来定义此功能吗?
非常感谢,
答案 0 :(得分:1)
你有
Prelude> let general_scanl2 f g z xs = concat $ zipWith g (scanl f z xs) xs
-- :: [a]
Prelude> :t general_scanl2
general_scanl2 :: (a -> b -> a) -- f
-> (a -> b -> [c]) -- g
-> a -- z
-> [b] -- xs
-> [c]
Prelude Data.List> :t mapAccumL
mapAccumL :: (a -> b -> (a, y)) -> a -> [b] -> (a, [y])
所以,写这个的另一种方式似乎是
import Data.List
g_scanl3 :: (a -> b -> a) -> (a -> b -> [c]) -> a -> [b] -> [c]
g_scanl3 f g z xs = concat . snd $
mapAccumL (\a b-> (f a b, g a b)) z xs