-- | /O(n)/. Build a set from an ascending list of distinct elements in linear time.
-- /The precondition (input list is strictly ascending) is not checked./
fromDistinctAscList :: [a] -> Set a
fromDistinctAscList xs
  = create const (length xs) xs
  where
    -- 1) use continutations so that we use heap space instead of stack space.
    -- 2) special case for n==5 to create bushier trees.
    create c 0 xs' = c Tip xs'
    create c 5 xs' = case xs' of
                       (x1:x2:x3:x4:x5:xx)
                            -> c (bin x4 (bin x2 (singleton x1) (singleton x3)) (singleton x5)) xx
                       _ -> error "fromDistinctAscList create 5"
    create c n xs' = seq nr $ create (createR nr c) nl xs'
      where nl = n `div` 2
            nr = n - nl - 1

    createR n c l (x:ys) = create (createB l x c) n ys
    createR _ _ _ []     = error "fromDistinctAscList createR []"
    createB l x c r zs   = c (bin x l r) zs

{--------------------------------------------------------------------
  Eq converts the set to a list. In a lazy setting, this
  actually seems one of the faster methods to compare two trees
  and it is certainly the simplest :-)
--------------------------------------------------------------------}
fromDistinctAscList :: [a] -> Set a
fromDistinctAscList xs
  = create const (length xs) xs
  where
    -- 1) use continutations so that we use heap space instead of stack space.
    -- 2) special case for n==5 to create bushier trees.
    create c 0 xs' = c Tip xs'
    create c 5 xs' = case xs' of
                       (x1:x2:x3:x4:x5:xx)
                            -> c (bin x4 (bin x2 (singleton x1) (singleton x3)) (singleton x5)) xx
                       _ -> error "fromDistinctAscList create 5"
    create c n xs' = seq nr $ create (createR nr c) nl xs'
      where nl = n `div` 2
            nr = n - nl - 1

    createR n c l (x:ys) = create (createB l x c) n ys
    createR _ _ _ []     = error "fromDistinctAscList createR []"
    createB l x c r zs   = c (bin x l r) zs

{--------------------------------------------------------------------
  Eq converts the set to a list. In a lazy setting, this
  actually seems one of the faster methods to compare two trees
  and it is certainly the simplest :-)
--------------------------------------------------------------------}
fromDistinctAscList xs
  = create const (length xs) xs
  where
    -- 1) use continutations so that we use heap space instead of stack space.
    -- 2) special case for n==5 to create bushier trees.
    create c 0 xs' = c Tip xs'
    create c 5 xs' = case xs' of
                       (x1:x2:x3:x4:x5:xx)
                            -> c (bin x4 (bin x2 (singleton x1) (singleton x3)) (singleton x5)) xx
                       _ -> error "fromDistinctAscList create 5"
    create c n xs' = seq nr $ create (createR nr c) nl xs'
      where nl = n `div` 2
            nr = n - nl - 1

    createR n c l (x:ys) = create (createB l x c) n ys
    createR _ _ _ []     = error "fromDistinctAscList createR []"
    createB l x c r zs   = c (bin x l r) zs

{--------------------------------------------------------------------
  Eq converts the set to a list. In a lazy setting, this
  actually seems one of the faster methods to compare two trees
  and it is certainly the simplest :-)
--------------------------------------------------------------------}