-
Notifications
You must be signed in to change notification settings - Fork 23
Open
Description
(Copied from nick8325/quickcheck#280 )
Data.Functor.Contravariant
is now in base
, and it includes the types
newtype Equivalence a = Equivalence { getEquivalence :: a -> a -> Bool }
newtype Comparison a = Comparison { getComparison :: a -> a -> Ordering }
and those would be really useful to generate for CoArbitrary
, for sort predicates and such. However, the standard Arbitrary
instance for them would not be useful, because they don't abide by the reflexivity, symmetry/antisymmetry, and transitivity laws at all.
However, I think I found a way. A CoArbitrary
type can be sort of "hashed" by using it on a Gen
:
cohash :: CoArbitrary a => QCGen -> Int -> a -> Int
cohash g n a = unGen (coarbitrary a $ MkGen $ \g0 n0 -> fst $ randomR (negate n0, n0) g0) g n
Here, the "size" of the generator represents the "fineness" of the hash.
With that, we can generate the instances as follows:
instance CoArbitrary a => Arbitrary (Equivalence a) where
arbitrary = MkGen $ \g n -> Equivalence $ \a b -> cohash g n a == cohash g n b
instance CoArbitrary a => Arbitrary (Comparison a) where
arbitrary = MkGen $ \g n -> Comparison $ \a b -> compare (cohash g n a) (cohash g n b)
(Incidentally, the type Predicate
also exists, but can be generated with the standard instance for a -> Bool
.)
Metadata
Metadata
Assignees
Labels
No labels