How can I write reverse by foldr efficiently in Haskell?

前端 未结 5 1575
误落风尘
误落风尘 2021-02-06 01:44

Note that the trivial solution

reverse a = foldr (\\b c -> c ++ [b] ) [] a

is not very efficient, because of the quadratic growth in complex

5条回答
  •  猫巷女王i
    2021-02-06 02:40

    Consider the following:

    foldr (<>) seed [x1, x2, ... xn] == x1 <> (x2 <> (... <> (xn <> seed)))
    

    Let's just "cut" it into pieces:

    (x1 <>) (x2 <>) ... (xn <>)  seed
    

    Now we have this bunch of functions, let's compose them:

    (x1 <>).(x2 <>). ... .(xn <>).id $ seed
    

    ((.), id) it's Endo monoid, so

    foldr (<>) seed xs == (appEndo . foldr (mappend.Endo.(<>)) mempty $ xs) seed
    

    For left fold we need just Dual monoid.

    leftFold (<>) seed xs = (appEndo . getDual . foldr (mappend . Dual . Endo . (<>)) mempty $ xs) seed
    

    (<>) = (:) and seed = []

    reverse' xs = (appEndo . getDual . foldr (mappend . Dual . Endo . (:)) mempty $ xs) []
    

    Or simple:

    reverse' xs = (appEndo . foldr (flip mappend . Endo . (:)) mempty $ xs) []
    reverse' xs = (foldr (flip (.) . (:)) id $ xs) []
    reverse' = flip (foldr (flip (.) . (:)) id) []
    

提交回复
热议问题