PartialOrd.hs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. {-# LANGUAGE TemplateHaskell #-}
  2. module Internal.Utils.PartialOrd
  3. ( ISet(ISet)
  4. , tests
  5. ) where
  6. import Agda.Utils.PartialOrd
  7. import Data.List ( (\\) )
  8. import Data.Set (Set)
  9. import qualified Data.Set as Set
  10. import Internal.Helpers
  11. ------------------------------------------------------------------------------
  12. -- * Properties
  13. instance Arbitrary PartialOrdering where
  14. arbitrary = arbitraryBoundedEnum
  15. -- | We test our properties on integer sets ordered by inclusion.
  16. newtype ISet = ISet { iset :: Inclusion (Set Int) }
  17. deriving (Eq, Ord, PartialOrd, Show)
  18. instance Arbitrary ISet where
  19. arbitrary = ISet . Inclusion . Set.fromList <$> listOf (choose (0, 8))
  20. -- | Any two elements are 'related' in the way 'comparable' computes.
  21. prop_comparable_related :: ISet -> ISet -> Bool
  22. prop_comparable_related (ISet a) (ISet b) =
  23. related a o b where o = comparable a b
  24. -- | @flip comparable a b == oppPO (comparable a b)@
  25. prop_oppPO :: ISet -> ISet -> Bool
  26. prop_oppPO (ISet a) (ISet b) =
  27. comparable a b == oppPO (comparable b a)
  28. -- | Auxiliary function: lists to sets = sorted duplicate-free lists.
  29. sortUniq :: [Ordering] -> [Ordering]
  30. sortUniq = Set.toAscList . Set.fromList
  31. -- | 'leqPO' is inclusion of the associated 'Ordering' sets.
  32. prop_leqPO_sound :: PartialOrdering -> PartialOrdering -> Bool
  33. prop_leqPO_sound p q =
  34. (p `leqPO` q) == null (toOrderings p \\ toOrderings q)
  35. -- | 'orPO' amounts to the union of the associated 'Ordering' sets.
  36. -- Except that 'orPO POLT POGT == POAny' which should also include 'POEQ'.
  37. prop_orPO_sound :: PartialOrdering -> PartialOrdering -> Bool
  38. prop_orPO_sound p q =
  39. (p `orPO` q) == fromOrderings (toOrderings p ++ toOrderings q)
  40. -- | 'orPO' is associative.
  41. prop_associative_orPO :: PartialOrdering -> PartialOrdering ->
  42. PartialOrdering -> Bool
  43. prop_associative_orPO = isAssociative orPO
  44. -- | 'orPO' is commutative.
  45. prop_commutative_orPO :: PartialOrdering -> PartialOrdering -> Bool
  46. prop_commutative_orPO = isCommutative orPO
  47. -- | 'orPO' is idempotent.
  48. prop_idempotent_orPO :: PartialOrdering -> Bool
  49. prop_idempotent_orPO = isIdempotent orPO
  50. -- | The dominant element wrt. 'orPO' is 'POAny'.
  51. prop_zero_orPO :: PartialOrdering -> Bool
  52. prop_zero_orPO = isZero POAny orPO
  53. -- | Soundness of 'seqPO'.
  54. --
  55. -- As QuickCheck test, this property is inefficient, see 'prop_seqPO'.
  56. property_seqPO :: ISet -> PartialOrdering -> ISet -> PartialOrdering ->
  57. ISet -> Property
  58. property_seqPO (ISet a) o (ISet b) p (ISet c) =
  59. related a o b && related b p c ==> related a (seqPO o p) c
  60. -- | A more efficient way of stating soundness of 'seqPO'.
  61. prop_seqPO :: ISet -> ISet -> ISet -> Bool
  62. prop_seqPO (ISet a) (ISet b) (ISet c) = related a o c
  63. where o = comparable a b `seqPO` comparable b c
  64. -- | 'PartialOrdering' is a monoid, i.e. 'seqPO' is associative and
  65. -- the unit of 'seqPO' is 'POEQ'.
  66. prop_monoid_seqPO :: Property3 PartialOrdering
  67. prop_monoid_seqPO = isMonoid
  68. -- | The zero of 'seqPO' is 'POAny'.
  69. prop_zero_seqPO :: PartialOrdering -> Bool
  70. prop_zero_seqPO = isZero POAny seqPO
  71. -- | 'seqPO' is also commutative.
  72. prop_commutative_seqPO :: PartialOrdering -> PartialOrdering -> Bool
  73. prop_commutative_seqPO = isCommutative seqPO
  74. -- | 'seqPO' is idempotent.
  75. prop_idempotent_seqPO :: PartialOrdering -> Bool
  76. prop_idempotent_seqPO = isIdempotent seqPO
  77. -- | 'seqPO' distributes over 'orPO'.
  78. prop_distributive_seqPO_orPO :: PartialOrdering -> PartialOrdering ->
  79. PartialOrdering -> Bool
  80. prop_distributive_seqPO_orPO = isDistributive seqPO orPO
  81. -- | The result of 'toOrderings' is a sorted list without duplicates.
  82. prop_sorted_toOrderings :: PartialOrdering -> Bool
  83. prop_sorted_toOrderings p =
  84. sortUniq os == os where os = toOrderings p
  85. -- | From 'Ordering' to 'PartialOrdering' and back is the identity.
  86. prop_toOrderings_after_fromOrdering :: Ordering -> Bool
  87. prop_toOrderings_after_fromOrdering o =
  88. toOrderings (fromOrdering o) == [o]
  89. -- | From 'PartialOrdering' to 'Orderings' and back is the identity.
  90. prop_fromOrderings_after_toOrderings :: PartialOrdering -> Bool
  91. prop_fromOrderings_after_toOrderings p =
  92. fromOrderings (toOrderings p) == p
  93. -- | From 'Orderings' to 'PartialOrdering' and back is the identity.
  94. -- Except for @[LT,GT]@ which is a non-canonical representative of 'POAny'.
  95. prop_toOrderings_after_fromOrderings :: NonEmptyList Ordering -> Bool
  96. prop_toOrderings_after_fromOrderings (NonEmpty os) =
  97. Set.fromList os `Set.isSubsetOf`
  98. Set.fromList (toOrderings (fromOrderings os))
  99. -- | Pairs are related iff both components are related.
  100. prop_related_pair :: ISet -> ISet -> ISet -> ISet -> PartialOrdering -> Bool
  101. prop_related_pair (ISet x1) (ISet x2) (ISet y1) (ISet y2) o =
  102. related (x1,x2) o (y1,y2) == (related x1 o y1 && related x2 o y2)
  103. -- | Comparing 'PartialOrdering's amounts to compare their representation as
  104. -- 'Ordering' sets.
  105. prop_comparable_PartialOrdering :: PartialOrdering -> PartialOrdering -> Bool
  106. prop_comparable_PartialOrdering p q =
  107. comparable p q == comparable (to p) (to q)
  108. where to = Inclusion . toOrderings
  109. ------------------------------------------------------------------------
  110. -- * All tests
  111. ------------------------------------------------------------------------
  112. -- Template Haskell hack to make the following $allProperties work
  113. -- under ghc-7.8.
  114. return [] -- KEEP!
  115. -- | All tests as collected by 'allProperties'.
  116. --
  117. -- Using 'allProperties' is convenient and superior to the manual
  118. -- enumeration of tests, since the name of the property is added
  119. -- automatically.
  120. tests :: TestTree
  121. tests = testProperties "Internal.Utils.PartialOrd" $allProperties