packages feed

liquidhaskell-0.8.2.0: docs/slides/BOS14/hs/start/03_Termination.hs

module Termination where

import Prelude hiding (gcd, mod, map, repeat, take)
import Language.Haskell.Liquid.Prelude

fac   :: Int -> Int

-------------------------------------------------------------------------
-- | Simple Termination
-------------------------------------------------------------------------

{-@ fac :: Nat -> Nat @-}
fac 0 = 1
fac 1 = 1
fac n = n * fac (n-1)




-------------------------------------------------------------------------
-- | Semantic Termination
-------------------------------------------------------------------------

gcd :: Int -> Int -> Int
gcd a 0 = a
gcd a b = gcd b (a `mod` b)


mod :: Int -> Int -> Int
mod a b | a - b >  b = mod (a - b) b
        | a - b <  b = a - b
        | a - b == b = 0

-------------------------------------------------------------------------
-- | Explicit Metrics #1 
-------------------------------------------------------------------------

tfac       :: Int -> Int -> Int
tfac acc 0 = acc
tfac acc n = tfac (n * acc) (n-1)




-------------------------------------------------------------------------
-- Explicit Metrics #2 
-------------------------------------------------------------------------

range :: Int -> Int -> [Int]
range lo hi
  | lo < hi   = lo : range (lo + 1) hi
  | otherwise = []



-------------------------------------------------------------------------
-- | Structural Recursion 
-------------------------------------------------------------------------

data List a = N | C a (List a)

{-@ measure size @-}
size          :: List a -> Int 
size (C x xs) = 1 + size xs
size (N)      = 0


map            :: (a -> b) -> List a -> List b
map _ N        = N
map f (C x xs) = f x `C` map f xs



-------------------------------------------------------------------------
-- | Default Metrics
-------------------------------------------------------------------------

map'            :: (a -> b) -> List a -> List b
map' _ N        = N
map' f (C x xs) = f x `C` map' f xs






-------------------------------------------------------------------------
-- | Termination Expressions Metrics
-------------------------------------------------------------------------

merge          :: (Ord a) => List a -> List a -> List a

merge (C x xs) (C y ys)
  | x < y      = x `C` merge xs (y `C` ys)
  | otherwise  = y `C` merge (x `C` xs) ys
merge _   ys   = ys

































--------------------------------------------------------------------------------
-- | CHEAT AREA ----------------------------------------------------------------
--------------------------------------------------------------------------------

-- # START ERRORS 8
-- # END ERRORS   0

{- gcd   :: a:Nat -> b:{v:Nat | v < a} -> Int @-}
{- mod   :: a:Nat -> b:{v:Nat| 0 < v && v < a} -> {v:Nat | v < b} @-}
{- tfac  :: Nat -> n:Nat -> Nat / [n] @-}
{- range :: lo:Nat -> hi:Nat -> [Nat] / [hi-lo] @-}
{- map   :: (a -> b) -> xs:List a -> (List b) / [size xs] @-}
{- merge :: xs:_ -> ys:_ -> _ / [size xs + size ys] @-}
{- data List [size] a = N | C {x :: a, xs :: List a } @-}




























--------------------------------------------------------------------------------
-- | BOILERPLATE ---------------------------------------------------------------
--------------------------------------------------------------------------------
                 
{-@ invariant {v : List a | 0 <= size v} @-}