Skip to content

Instantly share code, notes, and snippets.

@evincarofautumn
Last active August 11, 2020 18:12
Show Gist options
  • Save evincarofautumn/f589e3305489334015414d1c4c44d15a to your computer and use it in GitHub Desktop.
Save evincarofautumn/f589e3305489334015414d1c4c44d15a to your computer and use it in GitHub Desktop.
Zip from end of list
rzipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
rzipWith f xs0 ys0 = loop 0 0 xs0 ys0
where
loop x y = curry \ case
(_:xs, _:ys) -> loop (succ x) (succ y) xs ys
(xs, []) -> done (x + length xs) y
([], ys) -> done x (y + length ys)
done x y = zipWith f (dx xs0) (dy ys0)
where
d = y - x
(dx, dy)
| d < 0 = (drop (-d), id)
| otherwise = (id, drop d)
newtype Zip a b = Zip { runZip :: a -> (Zip a b -> b) -> b }
-- A version that fuses away both input lists!
-- Adapted from <https://www.reddit.com/r/haskell/comments/f3z18s/zipping_from_the_end_of_a_list/g14cgmh/>
rzipWith' :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
rzipWith' f xs ys
= foldl xf (const id) xs
(Zip (foldl yf (const (const id)) ys))
[]
where
xf
:: (Zip x y -> y)
-> x
-> Zip x y
-> y
xf k x = \ a -> runZip a x k
yf
:: (x -> (Zip x y -> y) -> y)
-> b
-> a
-> (Zip x y -> [c] -> r)
-> [c]
-> r
yf r2 y = \ x r1 zs -> r1 (Zip r2) (f x y : zs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment