-- {-# OPTIONS -v term:30 #-}
module TerminationArgumentSwapping where

-- subtyping simple types

data Bool : Set where
   true  : Bool
   false : Bool

_&&_ : Bool -> Bool -> Bool
true && a = a
false && a = false

data Ty : Set where
   bot : Ty
   top : Ty
   arr : Ty -> Ty -> Ty

subty : Ty -> Ty -> Bool
subty bot _ = true
subty _ top = true
subty (arr a b) (arr a' b') = subty a' a && subty b b'
subty _ _ = false


-- maximum with happy swapping

data Nat : Set where
    zero : Nat
    succ : Nat -> Nat

-- Maximum of 3 numbers

max3 : Nat -> Nat -> Nat -> Nat
max3 zero zero z = z
max3 zero y zero = y
max3 x zero zero = x
max3 (succ x) (succ y) zero = succ (max3 x y zero)
max3 (succ x) zero (succ z) = succ (max3 x z zero)
max3 zero (succ y) (succ z) = succ (max3 y z zero)
max3 (succ x) (succ y) (succ z) = succ (max3 z x y)

-- can also be done with sized types
-- max3 : Nat^i -> Nat^i -> Nat^i -> Nat^i

-- swapping with higher-order datatypes

data Ord : Set where
   ozero : Ord
   olim  : (Nat -> Ord) -> Ord

foo : Ord -> (Nat -> Ord) -> Ord
foo ozero    g = ozero
foo (olim f) g = olim (\n -> foo (g n) f)
