{-@ LIQUID "--no-termination" @-} module Times where import Foreign {-@ times :: forall

a -> Prop>. n:Nat -> a

-> (m:{Nat | m <= n} -> a

-> a

) -> a

@-} times :: Int -> a -> (Int -> a -> a) -> a times n z f = go 0 z where go m z | m == n = z | otherwise = go (m+1) (f m z) {-@ predicate Btwn Lo N Hi = Lo <= N && N < Hi @-} {-@ predicate Uint8 N = Btwn 0 N 256 @-} {-@ assume addUint8 :: x:{Int | Uint8 x} -> y:{Int | Uint8 y && Uint8 (x+y)} -> {v:Int | Uint8 v && v = x + y} @-} addUint8 :: Int -> Int -> Int addUint8 = (+) {-@ ten :: {v:Int | Uint8 v} @-} ten = times 10 0 (\n x -> add1 x) {-@ gt10 :: x:Int -> {v:Bool | Prop v <=> x >= 10} @-} gt10 :: Int -> Bool gt10 x = x >= 10 {-@ add1 :: x:{Int | Btwn 0 x 255} -> {v:Int | Uint8 v && v = x + 1} @-} add1 x = addUint8 x 1 {-@ qualif TimesTwo(v:int, x:int): v = x * 2 @-} {-@ qualif PlusTwo(v:int, x:int): v = x + 2 @-} timesM :: Int -> (Int -> IO ()) -> IO () timesM n f = go 0 where go m | m == n = return () | otherwise = f m >> go (m+1) {-@ tenM :: Ptr <{\x -> x = 0}> Int -> IO () @-} tenM :: Ptr Int -> IO () tenM p = timesM 10 $ \i -> do x <- peek p poke p $ x `addUint8` 1 {-@ data Ptr a

Prop> = GHC.Ptr.Ptr (x::GHC.Base.Addr#) @-} {-@ poke :: forall

Prop>. (Storable a) => Ptr

a -> a

-> (IO ()) @-} {-@ peek :: forall

Prop>. (Storable a) => (Ptr

a) -> (IO (a

)) @-}