module TerminationListInsertionNaive where

data List (A : Set) : Set where
  [] : List A
  _::_ : A -> List A -> List A

infixr 50 _::_

-- non-deterministic choice
postulate
  _⊕_ : {A : Set} -> A -> A -> A
infixl 10 _⊕_

-- a funny formulation of insert
-- insert (a :: l)  inserts a into l
--
-- this example cannot be handled with subpatterns
-- it is done with structured orders
-- could also be done with sized types

insert : {A : Set} -> List A -> List A
insert [] = []
insert (a :: []) = a :: []
insert (a :: b :: bs) = a :: b :: bs ⊕        -- case a <= b
                        b :: insert (a :: bs) -- case a > b


-- list flattening
-- termination using structured orders
flat : {A : Set} -> List (List A) -> List A
flat [] = []
flat ([] :: ll) = flat ll
flat ((x :: l) :: ll) = x :: flat (l :: ll)

{- generates two recursive calls with the following call matrices


      [] :: ll         (x :: l)   ll

  ll  <            l   <          .
                   ll  .          =

during composition, the second is collapsed to =, so the call graph is
already complete.  Both matrices are idempotent and contain a strictly
decreasing argument.

It could also be done with sized types; lexicographic in (i,j)
with type

  flat : {A : Set} -> (1 + Listʲ A × List^i (List^∞ A)) -> List^∞ A


-}
