{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE UndecidableInstances #-}

module Data.Registry.Hedgehog
  ( -- creation / tweaking functions
    Gen,
    Chooser (..),
    genFun,
    genVal,
    genWith,
    setGen,
    specializeGen,
    tweakGen,
    makeNonEmpty,
    genListOf,
    genListOfMinMax,
    genNonEmptyOfMinMax,
    genNonEmptyOf,
    genMaybeOf,
    genOneOf,
    genPairOf,
    genTripleOf,
    genTuple4Of,
    genMapOf,
    genNonEmptyMapOf,
    genHashMapOf,
    setDistinctPairOf,
    setDistinctPairOfOn,
    setDistinctTripleOf,
    setDistinctTripleOfOn,
    -- combinators to compose different types of generators
    distinctPairOf,
    distinctPairOfOn,
    distinctTripleOf,
    distinctTripleOfOn,
    eitherOf,
    hashMapOf,
    listOf,
    listOfMinMax,
    nonEmptyOfMinMax,
    mapOf,
    maybeOf,
    nonEmptyMapOf,
    nonEmptyOf,
    pairOf,
    setOf,
    setOfMinMax,
    tripleOf,
    tuple4Of,
    tuple5Of,
    -- choosing constructors in an ADT
    choiceChooser,
    chooseOne,
    -- sampling for Gen generators
    sampleIO,
  )
where

import Data.HashMap.Strict as HashMap (HashMap, fromList)
import qualified Data.List as L
import Data.List.NonEmpty as NonEmpty hiding (cycle, nonEmpty, (!!))
import Data.Map as Map (fromList)
import Data.Maybe as Maybe
import Data.Registry
import Data.Registry.Internal.Hedgehog
import Data.Set as Set (fromList)
import Hedgehog
import Hedgehog.Gen as Gen
import Hedgehog.Range
import Protolude as P

-- * CREATION / TWEAKING OF REGISTRY GENERATORS

-- | Create a Gen a for a given constructor of type a
genFun :: forall a b. (ApplyVariadic Gen a b, Typeable a, Typeable b) => a -> Typed b
genFun :: forall a b.
(ApplyVariadic Gen a b, Typeable a, Typeable b) =>
a -> Typed b
genFun = forall (m :: * -> *) a b.
(ApplyVariadic m a b, Typeable a, Typeable b) =>
a -> Typed b
funTo @Gen

-- | Create a Gen a for a given constructor of type a
genVal :: forall a. (Typeable a) => Gen a -> Typed (Gen a)
genVal :: forall a. Typeable a => Gen a -> Typed (Gen a)
genVal = forall a. Typeable a => a -> Typed a
fun

-- | Extract a generator from a registry
--   We use makeUnsafe assuming that the registry has been checked before
genWith :: forall a ins out. (Typeable a) => Registry ins out -> Gen a
genWith :: forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Registry ins out -> Gen a
genWith = forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Registry ins out -> a
make @(Gen a)

-- | Modify the value of a generator in a given registry
tweakGen :: forall a ins out. (Typeable a) => (a -> a) -> Registry ins out -> Registry ins out
tweakGen :: forall a (ins :: [*]) (out :: [*]).
Typeable a =>
(a -> a) -> Registry ins out -> Registry ins out
tweakGen a -> a
f = forall a (ins :: [*]) (out :: [*]).
Typeable a =>
(a -> a) -> Registry ins out -> Registry ins out
tweak @(Gen a) (a -> a
f <$>)

-- | Set a specific generator on the registry the value of a generator in a given registry
setGen :: forall a ins out. (Typeable a) => Gen a -> Registry ins out -> Registry ins out
setGen :: forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Gen a -> Registry ins out -> Registry ins out
setGen = forall a (ins :: [*]) (out :: [*]).
Typeable a =>
(a -> a) -> Registry ins out -> Registry ins out
tweak @(Gen a) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const

-- | Specialize a generator in a given context
specializeGen :: forall (a :: Type) b ins out. (Typeable a, Typeable b) => Gen b -> Registry ins out -> Registry ins out
specializeGen :: forall a b (ins :: [*]) (out :: [*]).
(Typeable a, Typeable b) =>
Gen b -> Registry ins out -> Registry ins out
specializeGen Gen b
g = forall {k1} {k2} (a :: k1) (b :: k2) (ins :: [*]) (out :: [*]).
Typeable a =>
Typed b -> Registry ins out -> Registry ins out
specialize @(Gen a) @(Gen b) (forall a. Typeable a => a -> Typed a
fun Gen b
g)

-- | Add a generator for a list of elements
genListOf :: forall a. (Typeable a) => Typed (Gen a -> Gen [a])
genListOf :: forall a. Typeable a => Typed (Gen a -> Gen [a])
genListOf = forall a. Typeable a => a -> Typed a
fun (forall a. Gen a -> Gen [a]
listOf @a)

-- | Add a generator for a bounded list of elements
genListOfMinMax :: forall a. (Typeable a) => Int -> Int -> Typed (Gen a -> Gen [a])
genListOfMinMax :: forall a. Typeable a => Int -> Int -> Typed (Gen a -> Gen [a])
genListOfMinMax Int
mn Int
mx = forall a. Typeable a => a -> Typed a
fun (forall a. Int -> Int -> Gen a -> Gen [a]
listOfMinMax @a Int
mn Int
mx)

-- | Add a generator for a non-empty list of elements
genNonEmptyOf :: forall a. (Typeable a) => Typed (Gen a -> Gen (NonEmpty a))
genNonEmptyOf :: forall a. Typeable a => Typed (Gen a -> Gen (NonEmpty a))
genNonEmptyOf = forall a. Typeable a => a -> Typed a
fun (forall a. Gen a -> Gen (NonEmpty a)
nonEmptyOf @a)

-- | Add a generator for a bounded non-empty list of elements
genNonEmptyOfMinMax :: forall a. (Typeable a) => Int -> Int -> Typed (Gen a -> Gen (NonEmpty a))
genNonEmptyOfMinMax :: forall a.
Typeable a =>
Int -> Int -> Typed (Gen a -> Gen (NonEmpty a))
genNonEmptyOfMinMax Int
mn Int
mx = forall a. Typeable a => a -> Typed a
fun (forall a. Int -> Int -> Gen a -> Gen (NonEmpty a)
nonEmptyOfMinMax @a Int
mn Int
mx)

-- | Add a generator for an optional element
genMaybeOf :: forall a. (Typeable a) => Typed (Gen a -> Gen (Maybe a))
genMaybeOf :: forall a. Typeable a => Typed (Gen a -> Gen (Maybe a))
genMaybeOf = forall a. Typeable a => a -> Typed a
fun (forall a. Gen a -> Gen (Maybe a)
maybeOf @a)

-- | Add a generator for a element picked from a list
genOneOf :: (Typeable a, Show a) => [a] -> Typed (Gen a)
genOneOf :: forall a. (Typeable a, Show a) => [a] -> Typed (Gen a)
genOneOf [a]
as = forall a. Typeable a => Gen a -> Typed (Gen a)
genVal (forall (m :: * -> *) a. MonadGen m => [a] -> m a
Gen.element [a]
as)

-- | Add a generator for a pair of elements
genPairOf :: forall a b. (Typeable a, Typeable b) => Typed (Gen a -> Gen b -> Gen (a, b))
genPairOf :: forall a b.
(Typeable a, Typeable b) =>
Typed (Gen a -> Gen b -> Gen (a, b))
genPairOf = forall a. Typeable a => a -> Typed a
fun (forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf @a @b)

-- | Add a generator for a triple of elements
genTripleOf :: forall a b c. (Typeable a, Typeable b, Typeable c) => Typed (Gen a -> Gen b -> Gen c -> Gen (a, b, c))
genTripleOf :: forall a b c.
(Typeable a, Typeable b, Typeable c) =>
Typed (Gen a -> Gen b -> Gen c -> Gen (a, b, c))
genTripleOf = forall a. Typeable a => a -> Typed a
fun (forall a b c. Gen a -> Gen b -> Gen c -> Gen (a, b, c)
tripleOf @a @b @c)

-- | Add a generator for 4 elements
genTuple4Of :: forall a b c d. (Typeable a, Typeable b, Typeable c, Typeable d) => Typed (Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d))
genTuple4Of :: forall a b c d.
(Typeable a, Typeable b, Typeable c, Typeable d) =>
Typed (Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d))
genTuple4Of = forall a. Typeable a => a -> Typed a
fun (forall a b c d.
Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d)
tuple4Of @a @b @c @d)

-- | Add a generator for a map of elements
genMapOf :: forall k v. (Ord k, Typeable k, Typeable v) => Typed (Gen k -> Gen v -> Gen (Map k v))
genMapOf :: forall k v.
(Ord k, Typeable k, Typeable v) =>
Typed (Gen k -> Gen v -> Gen (Map k v))
genMapOf = forall a. Typeable a => a -> Typed a
fun (forall k v. Ord k => Gen k -> Gen v -> Gen (Map k v)
mapOf @k @v)

-- | Add a generator for a non empty map of elements
genNonEmptyMapOf :: forall k v. (Ord k, Typeable k, Typeable v) => Typed (Gen k -> Gen v -> Gen (Map k v))
genNonEmptyMapOf :: forall k v.
(Ord k, Typeable k, Typeable v) =>
Typed (Gen k -> Gen v -> Gen (Map k v))
genNonEmptyMapOf = forall a. Typeable a => a -> Typed a
fun (forall k v. Ord k => Gen k -> Gen v -> Gen (Map k v)
nonEmptyMapOf @k @v)

-- | Add a generator for a hashmap of elements
genHashMapOf :: forall k v. (Ord k, Hashable k, Typeable k, Typeable v) => Typed (Gen k -> Gen v -> Gen (HashMap k v))
genHashMapOf :: forall k v.
(Ord k, Hashable k, Typeable k, Typeable v) =>
Typed (Gen k -> Gen v -> Gen (HashMap k v))
genHashMapOf = forall a. Typeable a => a -> Typed a
fun (forall k v.
(Ord k, Hashable k) =>
Gen k -> Gen v -> Gen (HashMap k v)
hashMapOf @k @v)

-- | Add the generation of a pair of distinct elements
setDistinctPairOf :: forall a. (Typeable a, Eq a) => Registry _ _ -> Registry _ _
setDistinctPairOf :: Registry ins out
-> Registry (GenT Identity a : ins) (GenT Identity (a, a) : out)
setDistinctPairOf Registry ins out
r = forall a. Typeable a => a -> Typed a
fun (forall a. Eq a => Gen a -> Gen (a, a)
distinctPairOf @a) forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Typed a
-> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)
+: Registry ins out
r

-- | Add the generation of a pair of distinct elements, according to one of their part
setDistinctPairOfOn :: forall a b. (Typeable a, Eq b) => (a -> b) -> Registry _ _ -> Registry _ _
setDistinctPairOfOn :: (a -> b)
-> Registry ins out
-> Registry (GenT Identity a : ins) (GenT Identity (a, a) : out)
setDistinctPairOfOn a -> b
f Registry ins out
r = forall a. Typeable a => a -> Typed a
fun (forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a)
distinctPairOfOn @a a -> b
f) forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Typed a
-> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)
+: Registry ins out
r

-- | Add the generation of a triple of distinct elements
setDistinctTripleOf :: forall a. (Typeable a, Eq a) => Registry _ _ -> Registry _ _
setDistinctTripleOf :: Registry ins out
-> Registry (GenT Identity a : ins) (GenT Identity (a, a, a) : out)
setDistinctTripleOf Registry ins out
r = forall a. Typeable a => a -> Typed a
fun (forall a. Eq a => Gen a -> Gen (a, a, a)
distinctTripleOf @a) forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Typed a
-> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)
+: Registry ins out
r

-- | Add the generation of a triple of distinct elements, according to one of their part
setDistinctTripleOfOn :: forall a b. (Typeable a, Eq b) => (a -> b) -> Registry _ _ -> Registry _ _
setDistinctTripleOfOn :: (a -> b)
-> Registry ins out
-> Registry (GenT Identity a : ins) (GenT Identity (a, a, a) : out)
setDistinctTripleOfOn a -> b
f Registry ins out
r = forall a. Typeable a => a -> Typed a
fun (forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a, a)
distinctTripleOfOn @a a -> b
f) forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Typed a
-> Registry ins out -> Registry (Inputs a :++ ins) (Output a : out)
+: Registry ins out
r

-- | Make sure there is always one element of a given type in a list of elements
makeNonEmpty :: forall (a :: Type) ins out. (Typeable a) => Registry ins out -> Registry ins out
makeNonEmpty :: forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Registry ins out -> Registry ins out
makeNonEmpty Registry ins out
r =
  -- extract a generator for one element only
  let genA :: Gen a
genA = forall a (ins :: [*]) (out :: [*]).
Typeable a =>
Registry ins out -> Gen a
genWith @a Registry ins out
r
   in -- add that element in front of a list of generated elements
      forall a (ins :: [*]) (out :: [*]).
Typeable a =>
(a -> a) -> Registry ins out -> Registry ins out
tweak @(Gen [a]) (\Gen [a]
genAs -> (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
genA forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen [a]
genAs) Registry ins out
r

-- * CONTAINERS COMBINATORS

-- | Create a generator for a pair
pairOf :: forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf :: forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf Gen a
ga Gen b
gb = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
ga forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen b
gb

-- | Create a generator for a triple
tripleOf :: forall a b c. Gen a -> Gen b -> Gen c -> Gen (a, b, c)
tripleOf :: forall a b c. Gen a -> Gen b -> Gen c -> Gen (a, b, c)
tripleOf Gen a
ga Gen b
gb Gen c
gc = (,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
ga forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen b
gb forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen c
gc

-- | Create a generator for a quadruple
tuple4Of :: forall a b c d. Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d)
tuple4Of :: forall a b c d.
Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d)
tuple4Of Gen a
ga Gen b
gb Gen c
gc Gen d
gd = (,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
ga forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen b
gb forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen c
gc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen d
gd

-- | Create a generator for a quintuple
tuple5Of :: forall a b c d e. Gen a -> Gen b -> Gen c -> Gen d -> Gen e -> Gen (a, b, c, d, e)
tuple5Of :: forall a b c d e.
Gen a -> Gen b -> Gen c -> Gen d -> Gen e -> Gen (a, b, c, d, e)
tuple5Of Gen a
ga Gen b
gb Gen c
gc Gen d
gd Gen e
ge = (,,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
ga forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen b
gb forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen c
gc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen d
gd forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen e
ge

-- | Create a default generator for a small list of elements
listOf :: forall a. Gen a -> Gen [a]
listOf :: forall a. Gen a -> Gen [a]
listOf = forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Gen.list (forall a. Integral a => a -> a -> Range a
linear Int
0 Int
10)

-- | Create a default generator for a list of elements of min elements and max elements
listOfMinMax :: forall a. Int -> Int -> Gen a -> Gen [a]
listOfMinMax :: forall a. Int -> Int -> Gen a -> Gen [a]
listOfMinMax Int
min' Int
max' = forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Gen.list (forall a. Integral a => a -> a -> Range a
linear Int
min' Int
max')

-- | Create a default generator for a small non-empty list of elements
nonEmptyOf :: Gen a -> Gen (NonEmpty a)
nonEmptyOf :: forall a. Gen a -> Gen (NonEmpty a)
nonEmptyOf = forall (m :: * -> *) a.
MonadGen m =>
Range Int -> m a -> m (NonEmpty a)
Gen.nonEmpty (forall a. Integral a => a -> a -> Range a
linear Int
1 Int
10)

-- | Create a default generator for a Maybe, choosing evenly between Nothing and Just
maybeOf :: forall a. Gen a -> Gen (Maybe a)
maybeOf :: forall a. Gen a -> Gen (Maybe a)
maybeOf Gen a
genA = forall (m :: * -> *) a. MonadGen m => [m a] -> m a
choice [forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing, forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
genA]

-- | Create a default generator for a Either, choosing evenly between Left and Right
eitherOf :: forall a b. Gen a -> Gen b -> Gen (Either a b)
eitherOf :: forall a b. Gen a -> Gen b -> Gen (Either a b)
eitherOf Gen a
genA Gen b
genB = forall (m :: * -> *) a. MonadGen m => [m a] -> m a
choice [forall a b. a -> Either a b
Left forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
genA, forall a b. b -> Either a b
Right forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen b
genB]

-- | Create a default generator for a small set of elements
setOf :: forall a. (Ord a) => Gen a -> Gen (Set a)
setOf :: forall a. Ord a => Gen a -> Gen (Set a)
setOf = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Ord a => [a] -> Set a
Set.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Gen a -> Gen [a]
listOf

-- | Create a default generator for a set with a minimum and a maximum number of elements
--   The implementation uses Gen.filter to make sure that the elements are unique
setOfMinMax :: forall a. (Ord a) => Int -> Int -> Gen a -> Gen (Set a)
setOfMinMax :: forall a. Ord a => Int -> Int -> Gen a -> Gen (Set a)
setOfMinMax Int
mi Int
mx = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Ord a => [a] -> Set a
Set.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
(MonadGen m, GenBase m ~ Identity) =>
(a -> Bool) -> m a -> m a
Gen.filter (\[a]
as -> forall a. Eq a => [a] -> [a]
L.nub [a]
as forall a. Eq a => a -> a -> Bool
== [a]
as) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> Int -> Gen a -> Gen [a]
listOfMinMax @a Int
mi Int
mx

-- | Create a default generator for map of key/values
mapOf :: forall k v. (Ord k) => Gen k -> Gen v -> Gen (Map k v)
mapOf :: forall k v. Ord k => Gen k -> Gen v -> Gen (Map k v)
mapOf Gen k
gk Gen v
gv = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf (forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf Gen k
gk Gen v
gv)

-- | Create a default generator for HashMap of key/values
hashMapOf :: forall k v. (Ord k, Hashable k) => Gen k -> Gen v -> Gen (HashMap k v)
hashMapOf :: forall k v.
(Ord k, Hashable k) =>
Gen k -> Gen v -> Gen (HashMap k v)
hashMapOf Gen k
gk Gen v
gv = forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HashMap.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
listOf (forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf Gen k
gk Gen v
gv)

-- | Create a default generator for a small non-empty map of elements
nonEmptyMapOf :: forall k v. (Ord k) => Gen k -> Gen v -> Gen (Map k v)
nonEmptyMapOf :: forall k v. Ord k => Gen k -> Gen v -> Gen (Map k v)
nonEmptyMapOf Gen k
gk Gen v
gv = do
  (k, v)
h <- forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf Gen k
gk Gen v
gv
  [(k, v)]
t <- forall a. Gen a -> Gen [a]
listOf (forall a b. Gen a -> Gen b -> Gen (a, b)
pairOf Gen k
gk Gen v
gv)
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ((k, v)
h forall a. a -> [a] -> [a]
: [(k, v)]
t))

-- | Make a generator for a non empty list of elements of a given type
nonEmptyOfMinMax :: Int -> Int -> Gen a -> Gen (NonEmpty a)
nonEmptyOfMinMax :: forall a. Int -> Int -> Gen a -> Gen (NonEmpty a)
nonEmptyOfMinMax Int
mi Int
ma Gen a
g = forall a. [a] -> NonEmpty a
NonEmpty.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Int -> Int -> Gen a -> Gen [a]
listOfMinMax Int
mi Int
ma Gen a
g

-- | Make a generator for a pair of distinct values
distinctPairOf :: forall a. (Eq a) => Gen a -> Gen (a, a)
distinctPairOf :: forall a. Eq a => Gen a -> Gen (a, a)
distinctPairOf = forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a)
distinctPairOfOn forall a. a -> a
identity

-- | Make a generator for a pair of distinct values according to one of their part
distinctPairOfOn :: forall a b. (Eq b) => (a -> b) -> Gen a -> Gen (a, a)
distinctPairOfOn :: forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a)
distinctPairOfOn a -> b
f Gen a
genA = forall (m :: * -> *) a. MonadGen m => (a -> Bool) -> m a -> m a
Gen.filterT (\(a
a1, a
a2) -> a -> b
f a
a1 forall a. Eq a => a -> a -> Bool
/= a -> b
f a
a2) forall a b. (a -> b) -> a -> b
$ (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
genA forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
genA

-- | Make a generator for a triple of distinct values
distinctTripleOf :: forall a. (Eq a) => Gen a -> Gen (a, a, a)
distinctTripleOf :: forall a. Eq a => Gen a -> Gen (a, a, a)
distinctTripleOf = forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a, a)
distinctTripleOfOn forall a. a -> a
identity

-- | Make a generator for a triple of distinct values according to one of their part
distinctTripleOfOn :: forall a b. (Eq b) => (a -> b) -> Gen a -> Gen (a, a, a)
distinctTripleOfOn :: forall a b. Eq b => (a -> b) -> Gen a -> Gen (a, a, a)
distinctTripleOfOn a -> b
f Gen a
genA = forall (m :: * -> *) a. MonadGen m => (a -> Bool) -> m a -> m a
Gen.filterT (\(a
a1, a
a2, a
a3) -> a -> b
f a
a1 forall a. Eq a => a -> a -> Bool
/= a -> b
f a
a2 Bool -> Bool -> Bool
&& a -> b
f a
a2 forall a. Eq a => a -> a -> Bool
/= a -> b
f a
a3 Bool -> Bool -> Bool
&& a -> b
f a
a1 forall a. Eq a => a -> a -> Bool
/= a -> b
f a
a3) forall a b. (a -> b) -> a -> b
$ (,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
genA forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
genA forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
genA