foldr :: (a -> b -> b) -> b -> IntMap a -> b
foldr f z = start
  where
    start (IntMap (WordMap Empty)) = z
    start (IntMap (WordMap (NonEmpty _ minV Tip))) = f minV z
    start (IntMap (WordMap (NonEmpty min minV (Bin max maxV l r))))
        | w2i (xor min max) < 0 = goR r (f maxV (f minV (goL l z)))
        | otherwise = f minV (goL l (goR r (f maxV z)))
    
    goL Tip acc = acc
    goL (Bin _ maxV l r) acc = goL l (goR r (f maxV acc))
    
    goR Tip acc = acc
    goR (Bin _ minV l r) acc = f minV (goL l (goR r acc))

-- | /O(n)/. Fold the values in the map using the given left-associative
-- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.
--
-- For example,
--
-- > elems = reverse . foldl (flip (:)) []
--
-- > let f len a = len + (length a)
-- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4

foldr :: (a -> b -> b) -> b -> IntMap a -> b
foldr f z = start
  where
    start (IntMap (WordMap Empty)) = z
    start (IntMap (WordMap (NonEmpty _ minV Tip))) = f minV z
    start (IntMap (WordMap (NonEmpty min minV (Bin max maxV l r))))
        | w2i (xor min max) < 0 = goR r (f maxV (f minV (goL l z)))
        | otherwise = f minV (goL l (goR r (f maxV z)))
    
    goL Tip acc = acc
    goL (Bin _ maxV l r) acc = goL l (goR r (f maxV acc))
    
    goR Tip acc = acc
    goR (Bin _ minV l r) acc = f minV (goL l (goR r acc))

-- | /O(n)/. Fold the values in the map using the given left-associative
-- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.
--
-- For example,
--
-- > elems = reverse . foldl (flip (:)) []
--
-- > let f len a = len + (length a)
-- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4

foldr f z = start
  where
    start (IntMap (WordMap Empty)) = z
    start (IntMap (WordMap (NonEmpty _ minV Tip))) = f minV z
    start (IntMap (WordMap (NonEmpty min minV (Bin max maxV l r))))
        | w2i (xor min max) < 0 = goR r (f maxV (f minV (goL l z)))
        | otherwise = f minV (goL l (goR r (f maxV z)))
    
    goL Tip acc = acc
    goL (Bin _ maxV l r) acc = goL l (goR r (f maxV acc))
    
    goR Tip acc = acc
    goR (Bin _ minV l r) acc = f minV (goL l (goR r acc))

-- | /O(n)/. Fold the values in the map using the given left-associative
-- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'elems'@.
--
-- For example,
--
-- > elems = reverse . foldl (flip (:)) []
--
-- > let f len a = len + (length a)
-- > foldl f 0 (fromList [(5,"a"), (3,"bbb")]) == 4
