2014-01-24 46 views
1

我想寫一種scanl的樣型功能:「廣義」 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˚Fx和y),這是沒有必要的名單...

我的問題:是有定義此功能的更清潔的方式?

非常感謝,

+2

FYI':T general_scanl」 ::(甲 - >乙 - > a) - >(a - > b - > [c]) - > a - > [b] - > [c]' – Squidly

+2

請修正類型或示例函數(如MrBones指出的)目前不知道你在問什麼。儘管如此,第二個'general_scanl'是好的,比第一個更受歡迎。第一個是不必要的嚴格,如果'y'是無限的,它將會發散。第二是懶惰,同樣快。 –

+0

感謝您的意見。我相信我現在已經修復了這種類型。 – dumb0

回答

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 
+0

我會研究你的建議和Arrow模塊。如果滿意,我會接受答案。謝謝。 – dumb0

+0

'Arrow'只用於它的'(&&&)f g x =(f x,g x)'。 –

+0

mapAccumL就是我以後的樣子!我也對Arrows很好奇,謝謝。接受答案。 – dumb0