packages feed

liquidhaskell-0.8.10.7: benchmarks/popl18/nople/pos/Peano.hs

{-@ LIQUID "--higherorder"     @-}
{-@ LIQUID "--exact-data-cons" @-}
{-@ LIQUID "--higherorderqs" @-}

module Peano where

import Prelude hiding (plus)


import Language.Haskell.Liquid.ProofCombinators

-- Why do we need these?
zeroR     :: Peano -> Proof
zeroL     :: Peano -> Proof
plusAssoc :: Peano -> Peano -> Peano -> Proof
plusComm  :: Peano -> Peano -> Proof
plusSuccR :: Peano -> Peano -> Proof



data Peano = Z | S Peano

{-@ data Peano [toInt] = Z | S {prev :: Peano} @-}

{-@ measure toInt @-}
toInt :: Peano -> Int

{-@ toInt :: Peano -> Nat @-}
toInt Z     = 0
toInt (S n) = 1 + toInt n

{-@ axiomatize plus @-}
plus :: Peano -> Peano -> Peano
plus Z m     = m
plus (S n) m = S (plus n m)

{-@ zeroL :: n:Peano -> { plus Z n == n }  @-}
zeroL n
  =   plus Z n
  === n
  *** QED

{-@ zeroR :: n:Peano -> { plus n Z == n }  @-}
zeroR Z
  = plus Z Z
  === Z
  *** QED

zeroR (S n)
  =   plus (S n) Z
  === S (plus n Z)
    ? zeroR n
  === S n
  *** QED

{-@ plusSuccR :: n:Peano -> m:Peano -> { plus n (S m) = S (plus n m) } @-}
plusSuccR Z m
  =   plus Z (S m)
  === S m
  === S (plus Z m)
  *** QED

plusSuccR (S n) m
  =   plus (S n) (S m)
  === S (plus n (S m))
      ? plusSuccR n m
  === S (S (plus n m)) 
  === S (plus (S n) m)
  *** QED

{-@ plusComm :: a:_ -> b:_  -> {plus a b == plus b a} @-}
plusComm Z b
  =   plus Z b
      ? zeroR b
  === plus b Z 
  *** QED

plusComm (S a) b
  =   plus (S a) b
  === S (plus a b)
    ? plusComm a b
  === S (plus b a) 
    ? plusSuccR b a
  === plus b (S a)      
  *** QED

{-@ plusAssoc :: a:_ -> b:_ -> c:_ -> {plus (plus a b) c == plus a (plus b c) } @-}
plusAssoc Z b c
  =   plus (plus Z b) c
  === plus b c
  === plus Z (plus b c)
  *** QED

plusAssoc (S a) b c
  =   plus (plus (S a) b) c
  === plus (S (plus a b)) c
  === S (plus (plus a b) c)
    ? plusAssoc a b c
  === S (plus a (plus b c)) 
  === plus (S a) (plus b c)
  *** QED