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

    goL acc Tip = acc
    goL acc (Bin max maxV l r) = s f' (s goR (s goL acc l) r) max maxV
    
    goR acc Tip = acc
    goR acc (Bin min minV l r) = s goR (s goL (s f' acc min minV) l) r
    
    f' a k b = f a (w2i k) b
    
    s = ($!)

-- TODO: make the conversion functions good producers

-- | /O(n)/.
-- Return all elements of the map in the ascending order of their keys.
-- Subject to list fusion.
--
-- > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]
-- > elems empty == []
foldlWithKey' :: (a -> Key -> b -> a) -> a -> IntMap b -> a
foldlWithKey' f z = start
  where
    start (IntMap (WordMap Empty)) = z
    start (IntMap (WordMap (NonEmpty min minV Tip))) = s f' z min minV
    start (IntMap (WordMap (NonEmpty min minV (Bin max maxV l r))))
        | w2i (xor min max) < 0 = s goL (s f' (s f' (s goR z r) max maxV) min minV) l
        | otherwise = s f' (s goR (s goL (s f' z min minV) l) r) max maxV

    goL acc Tip = acc
    goL acc (Bin max maxV l r) = s f' (s goR (s goL acc l) r) max maxV
    
    goR acc Tip = acc
    goR acc (Bin min minV l r) = s goR (s goL (s f' acc min minV) l) r
    
    f' a k b = f a (w2i k) b
    
    s = ($!)

-- TODO: make the conversion functions good producers

-- | /O(n)/.
-- Return all elements of the map in the ascending order of their keys.
-- Subject to list fusion.
--
-- > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]
-- > elems empty == []
foldlWithKey' f z = start
  where
    start (IntMap (WordMap Empty)) = z
    start (IntMap (WordMap (NonEmpty min minV Tip))) = s f' z min minV
    start (IntMap (WordMap (NonEmpty min minV (Bin max maxV l r))))
        | w2i (xor min max) < 0 = s goL (s f' (s f' (s goR z r) max maxV) min minV) l
        | otherwise = s f' (s goR (s goL (s f' z min minV) l) r) max maxV

    goL acc Tip = acc
    goL acc (Bin max maxV l r) = s f' (s goR (s goL acc l) r) max maxV
    
    goR acc Tip = acc
    goR acc (Bin min minV l r) = s goR (s goL (s f' acc min minV) l) r
    
    f' a k b = f a (w2i k) b
    
    s = ($!)

-- TODO: make the conversion functions good producers

-- | /O(n)/.
-- Return all elements of the map in the ascending order of their keys.
-- Subject to list fusion.
--
-- > elems (fromList [(5,"a"), (3,"b")]) == ["b","a"]
-- > elems empty == []