packages feed

liquidhaskell-0.8.0.2: docs/slides/Galois2014/001_Refinements.hs

{-@ LIQUID "--short-names"    @-}
{-@ LIQUID "--no-warnings"    @-}
{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--totality"       @-}
{-@ LIQUID "--smtsolver=cvc4" @-}

module Refinements where

import Prelude hiding (map, foldr, foldr1)

divide    :: Int -> Int -> Int
-----------------------------------------------------------------------
-- | Our first Data Type
-----------------------------------------------------------------------

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

infixr 9 `C`

-----------------------------------------------------------------------
-- | A few Higher-Order Functions
-----------------------------------------------------------------------

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


foldr                :: (a -> b -> b) -> b -> List a -> b 
foldr f acc N        = acc
foldr f acc (C x xs) = f x (foldr f acc xs)


-- Uh oh. How shall we fix the error? Lets move on for now...

foldr1           :: (a -> a -> a) -> List a -> a   
foldr1 f (C x xs)    = foldr f x xs
-- foldr1 f N           = die "foldr1"



-- foldr1 f zs = case zs of
--   C x xs -> foldr f x xs
--   N      -> GHC.patError "YIKES"


-----------------------------------------------------------------------
-- | Measuring the Size of Data
-----------------------------------------------------------------------

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


-- N :: {v:List a | size v = 0}
-- C :: x:a -> xs:List a
--   -> {v:List a | size v = 1 + size xs}


append N        ys = ys
append (C x xs) ys = C x (append xs ys)



-----------------------------------------------------------------------
-- | Definitions from 000_Refinements.hs
-----------------------------------------------------------------------

{-@ type Nat     = {v:Int | v >= 0} @-}
{-@ type Pos     = {v:Int | v >  0} @-}
{-@ type NonZero = {v:Int | v /= 0} @-}

{-@ die :: {v:_ | false} -> a @-}
die msg = error msg

{-@ divide :: Int -> NonZero -> Int @-}
divide x 0 = die "divide-by-zero"
divide x n = x `div` n

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

-- # START-ERRORS 1 (foldr1)
-- # END-ERRORS   0

{- map    :: _ -> xs:_ -> {v:_ | size v = size xs}               @-}
{- append :: xs:_ -> ys:_ -> {v: _ | size v = size ys + size xs} @-}
{- foldr1 :: (a -> a -> a) -> {v:List a | size v > 0} -> a       @-}