altInsert e0 (Node _ e1 l r) = create upper l0 r0 where
  (l0, r0) = cascadeInsert (l, r)
  (upper, lower)
    | e0 <= e1  = (e0, e1)
    | otherwise = (e1, e0)

  cascadeInsert (h, Leaf) = (h, singleton lower)
  cascadeInsert (Leaf, h) = (h, singleton lower)
  cascadeInsert hs@(Node _ x _ _, Node _ y _ _)
    | x > y     = first  (altInsert lower) hs
    | otherwise = second (altInsert lower) hs

-- exercise 3.3 (implement alternate fromList)
-- - foldup halves list length on each pass, log n foldups
altInsert e0 (Node _ e1 l r) = create upper l0 r0 where
  (l0, r0) = cascadeInsert (l, r)
  (upper, lower)
    | e0 <= e1  = (e0, e1)
    | otherwise = (e1, e0)

  cascadeInsert (h, Leaf) = (h, singleton lower)
  cascadeInsert (Leaf, h) = (h, singleton lower)
  cascadeInsert hs@(Node _ x _ _, Node _ y _ _)
    | x > y     = first  (altInsert lower) hs
    | otherwise = second (altInsert lower) hs

-- exercise 3.3 (implement alternate fromList)
-- - foldup halves list length on each pass, log n foldups
altInsert e0 (Node _ e1 l r) = create upper l0 r0 where
  (l0, r0) = cascadeInsert (l, r)
  (upper, lower)
    | e0 <= e1  = (e0, e1)
    | otherwise = (e1, e0)

  cascadeInsert (h, Leaf) = (h, singleton lower)
  cascadeInsert (Leaf, h) = (h, singleton lower)
  cascadeInsert hs@(Node _ x _ _, Node _ y _ _)
    | x > y     = first  (altInsert lower) hs
    | otherwise = second (altInsert lower) hs

-- exercise 3.3 (implement alternate fromList)
-- - foldup halves list length on each pass, log n foldups