1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE KindSignatures #-}
4{-# LANGUAGE PolyKinds #-}
6{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
8module Test.TypeRep.MapProperty where
10import Prelude hiding (lookup)
12import Data.Proxy (Proxy (..))
13import Data.Semigroup (Semigroup (..))
14import GHC.Exts (fromList)
15import GHC.Stack (HasCallStack)
16import GHC.TypeLits (Nat, SomeNat (..), someNatVal)
17import Hedgehog (MonadGen, PropertyT, forAll, property, (===))
18import Test.Tasty (TestName, TestTree)
19import Test.Tasty.Hedgehog (testProperty)
21import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), delete, insert, lookup, member)
23import qualified Hedgehog.Gen as Gen
24import qualified Hedgehog.Range as Range
26----------------------------------------------------------------------------
28----------------------------------------------------------------------------
30type PropertyTest = [TestTree]
32prop :: HasCallStack => TestName -> PropertyT IO () -> PropertyTest
33prop testName = pure . testProperty testName . property
35----------------------------------------------------------------------------
36-- Map modification properties
37----------------------------------------------------------------------------
39test_InsertLookup :: PropertyTest
40test_InsertLookup = prop "lookup k (insert k v m) == Just v" $ do
42 WrapTypeable (proxy :: IntProxy n) <- forAll genTF
44 lookup @n @IntProxy (insert proxy m) === Just proxy
46test_InsertInsert :: PropertyTest
47test_InsertInsert = prop "insert k b . insert k a == insert k b" $ do
49 WrapTypeable a@(IntProxy (proxy :: Proxy n) i) <- forAll genTF
50 let b = IntProxy proxy (i + 1)
51 lookup @n @IntProxy (insert b $ insert a m) === Just b
53test_DeleteMember :: PropertyTest
54test_DeleteMember = prop "member k . delete k == False" $ do
56 WrapTypeable (proxy :: IntProxy n) <- forAll genTF
57 shouldInsert <- forAll Gen.bool
60 member @n (delete @n $ insert proxy m) === False
62 member @n (delete @n m) === False
64----------------------------------------------------------------------------
65-- Semigroup and Monoid laws
66----------------------------------------------------------------------------
68-- This newtype is used to compare 'TypeRepMap's using only 'Fingerprint's. It's
69-- not a good idea to write such `Eq` instance for `TypeRepMap` itself because
70-- it doesn't compare values so it's not true equality. But this should be
72newtype FpMap f = FpMap (TypeRepMap f)
73 deriving (Show, Semigroup, Monoid)
75instance Eq (FpMap f) where
76 FpMap (TypeRepMap as1 bs1 _ _) == FpMap (TypeRepMap as2 bs2 _ _) =
77 as1 == as2 && bs1 == bs2
79test_SemigroupAssoc :: PropertyTest
80test_SemigroupAssoc = prop "x <> (y <> z) == (x <> y) <> z" $ do
81 x <- FpMap <$> forAll genMap
82 y <- FpMap <$> forAll genMap
83 z <- FpMap <$> forAll genMap
85 (x <> (y <> z)) === ((x <> y) <> z)
87test_MonoidIdentity :: PropertyTest
88test_MonoidIdentity = prop "x <> mempty == mempty <> x == x" $ do
89 x <- FpMap <$> forAll genMap
94----------------------------------------------------------------------------
96----------------------------------------------------------------------------
98data IntProxy (n :: Nat) = IntProxy (Proxy n) Int
101genMap :: MonadGen m => m (TypeRepMap IntProxy)
102genMap = fromList <$> Gen.list (Range.linear 0 1000) genTF
104genTF :: MonadGen m => m (WrapTypeable IntProxy)
106 randNat :: Integer <- Gen.integral (Range.linear 0 10000)
107 randInt <- Gen.int Range.constantBounded
108 case someNatVal randNat of
109 Just (SomeNat proxyNat) -> pure $ WrapTypeable $ IntProxy proxyNat randInt
110 Nothing -> error "Invalid test generator"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list