packages feed

liquidhaskell-0.8.2.0: tests/todo/list-screen.hs

{-@ LIQUID "--no-termination" @-}

module ListDemo where

-----------------------------------------------------------------------
-- 1. Lets define a List data-type
-----------------------------------------------------------------------

data List a = E | (:::) { h :: a, t :: List a }

-- We'll want to use the "cons" in an infix fashion

infixr  9 ::: 

-- Ok, now here are some lists

aList :: List Int
aList = 0 ::: 2 ::: 7 ::: E

-- Lets define some simple refinements.

-- | The set of things  that are greater then `N`

{-@ type Geq a N = {v:a | N <= v} @-}

-- | now we can define the *natural* and *positive* numbers as:

{-@ type Nat   = Geq Int 0    @-}
{-@ type Grand = Geq Int 1000 @-}

-- > Lets go back and see if we can refine our lists:

{- up  :: List Grand @-}

-- Whoops, that didn't work of course, how about

{- up  :: List Nat  @-}

-----------------------------------------------------------------------
-- 2. Lets write a function that generates a sequence: n, n+1, n+2, ...
-----------------------------------------------------------------------

{-@ countUp :: n:Nat -> List Nat @-}
countUp n  = n ::: countUp (n + 1)

-- > How shall we type it? Well, one option:

{- countUp :: n:Nat -> List Nat @-}

-- So if you start with a `Nat` you get a list of `Nat`

-- > How about 

{- countUp :: n:Nat -> List Grand @-}

-- Of course not! Lets see the error. Ah, so you can do:

{- countUp :: n:Grand -> List Grand @-}


-----------------------------------------------------------------------
-- 3. ORDERED sequences ...
-----------------------------------------------------------------------

-- Now, really we want to say that `countUp` returns ORDERED sequences,
-- i.e. it returns an INCREASING list of numbers (starting at `n`).

-- Lets specify this by REFINING `List` to only allow INCREASING sequences ...

-- > Lets look at the data type.
-- > Key: INCREASING means `t` must ONLY contain values GREATER THAN head `h`.
                                      
-- that is,

-- t :: List (Geq a h)

-- lets specify that in a REFINED definition of `List`

{-@ data List a = E | (:::) { h :: a, t :: List (Geq a h) } @-}

-- Now lets look at some lists

ups = 0 ::: 1 ::: 3 ::: E 

-- But how about

downs = 7 ::: 2 ::: E

-- > Now lets go back and revisit `countUp` ... whoops there is an ERROR!
-- > This is because we only know the TAIL is a list of Nat, we ALSO need that
-- > the tail is greater than `n` and so ...

{- countUp :: n:Nat -> List (Geq n) @-}


insert x E          = x ::: E
insert x (y ::: ys)
  | x <= y          = x ::: y ::: ys
  | otherwise       = y ::: insert x ys