“广义”扫描

时间:2014-01-24 10:38:29

标签: haskell higher-order-functions

我正在尝试编写一种类似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),这是不必要的......

我的问题:有更简洁的方法来定义此功能吗?

非常感谢,

1 个答案:

答案 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