lean-peano-0.1.0.0: test/Spec.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Numeric.Peano
import Control.Monad
import Data.Ix
binaryProp
:: forall a.
Integral a
=> (forall t. Integral t => t -> t -> t)
-> Integer
-> Integer
-> (Integer -> Integer -> Bool)
-> Property
binaryProp op lb ub cond = property $ do
x <- forAll (Gen.integral (Range.linear lb ub))
y <- forAll (Gen.integral (Range.linear lb ub))
guard (cond x y)
let zb = op x y
let zt = op (fromInteger @a x) (fromInteger y)
zb === toInteger zt
holdsForLength :: Foldable f => (a -> Bool) -> f a -> Int
holdsForLength p = flip (foldr f id) 0 where
f e a i | p e = a (i + 1)
| otherwise = i
enumProps
:: forall a.
(Enum a, Show a, Ord a)
=> (Int -> Bool) -> Gen Int -> Gen a -> Property
enumProps p ig eg = property $ do
x <- forAll ig
annotate "from . to"
(fromEnum . toEnum @a) x === x
annotate "to . from"
n <- forAll eg
(toEnum . fromEnum) n === n
annotate "[n..]"
let lhs1 = take 100 $ map fromEnum [n..]
rhs1 = take 100 [fromEnum n..]
len1 = min (holdsForLength p lhs1) (holdsForLength p rhs1)
take len1 lhs1 === take len1 rhs1
annotate "[n,m..]"
m <- forAll eg
let lhs2 = take 100 $ map fromEnum [n,m..]
rhs2 = take 100 [fromEnum n, fromEnum m..]
len2 = min (holdsForLength p lhs2) (holdsForLength p rhs2)
take len2 lhs2 === take len2 rhs2
when (m >= n) $ do
annotate "[n..m]"
map fromEnum [n..m] === [fromEnum n..fromEnum m]
l <- forAll eg
when (((l > n) == (n > m)) && (l /= n)) $ do
annotate "[l,n..m]"
map fromEnum [l,n..m] === [fromEnum l, fromEnum n..fromEnum m]
prop_PeanoAdd :: Property
prop_PeanoAdd = binaryProp @Nat (+) 0 1000 (\_ _ -> True)
prop_PeanoMul :: Property
prop_PeanoMul = binaryProp @Nat (*) 0 1000 (\_ _ -> True)
prop_PeanoSub :: Property
prop_PeanoSub = withDiscards 1000 $ binaryProp @Nat (-) 0 1000 (>=)
prop_PeanoRem :: Property
prop_PeanoRem = binaryProp @Nat rem 0 1000 (\_ y -> y > 0)
prop_PeanoQuot :: Property
prop_PeanoQuot = binaryProp @Nat quot 0 1000 (\_ y -> y > 0)
-- prop_PeanoOrd :: Property
-- prop_PeanoOrd = property $ ord (Gen.integral (Range.linear @Nat 0 1000))(\n -> Gen.integral (Range.linear n (n+5)))
prop_PeanoEnum :: Property
prop_PeanoEnum =
enumProps
(>= 0)
(Gen.integral (Range.linear 0 1000))
(Gen.integral (Range.linear @Nat 0 1000))
prop_PeanoInRange :: Property
prop_PeanoInRange = property $ do
l <- forAll (Gen.integral (Range.linear Z 100))
u <- forAll (Gen.integral (Range.linear l (l+100)))
i <- forAll (Gen.integral (Range.linear 0 300))
inRange (l,u) i === (l <= i && i <= u)
prop_PeanoIndex :: Property
prop_PeanoIndex = property $ do
l <- forAll (Gen.integral (Range.linear Z 100))
u <- forAll (Gen.integral (Range.linear l (l+100)))
i <- forAll (Gen.integral (Range.linear l u))
unless (inRange (l,u) i) discard
index (l,u) i === fromEnum (i - l)
main :: IO Bool
main = checkParallel $$(discover)