{-# OPTIONS_GHC -fno-warn-orphans #-}

module Data.GenValidity.Set
  ( genSetOf,
    shrinkSetOf,
    genSeperate,
    genSeperateFor,
    genSeperateForNE,
    genValidSeperateFor,
    genValidSeperateForNE,
  )
where

import Data.Containers.ListUtils
import Data.GenValidity
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Set (Set)
import qualified Data.Set as S
import Data.Validity.Set ()
import Test.QuickCheck

instance (Ord v, GenValid v) => GenValid (Set v) where
  genValid :: Gen (Set v)
genValid = forall v. Ord v => Gen v -> Gen (Set v)
genSetOf forall a. GenValid a => Gen a
genValid
  shrinkValid :: Set v -> [Set v]
shrinkValid = forall v. Ord v => (v -> [v]) -> Set v -> [Set v]
shrinkSetOf forall a. GenValid a => a -> [a]
shrinkValid

genSetOf :: Ord v => Gen v -> Gen (Set v)
genSetOf :: forall v. Ord v => Gen v -> Gen (Set v)
genSetOf Gen v
g = forall a. Ord a => [a] -> Set a
S.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
genListOf Gen v
g

shrinkSetOf :: Ord v => (v -> [v]) -> Set v -> [Set v]
shrinkSetOf :: forall v. Ord v => (v -> [v]) -> Set v -> [Set v]
shrinkSetOf v -> [v]
shrinker = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Ord a => [a] -> Set a
S.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> [a]) -> [a] -> [[a]]
shrinkList v -> [v]
shrinker forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Set a -> [a]
S.toList

genValidSeperateFor :: (GenValid b, Eq b) => [a] -> Gen [(b, a)]
genValidSeperateFor :: forall b a. (GenValid b, Eq b) => [a] -> Gen [(b, a)]
genValidSeperateFor = forall b a. Eq b => Gen b -> [a] -> Gen [(b, a)]
genSeperateFor forall a. GenValid a => Gen a
genValid

genValidSeperateForNE :: (GenValid b, Eq b) => NonEmpty a -> Gen (NonEmpty (b, a))
genValidSeperateForNE :: forall b a.
(GenValid b, Eq b) =>
NonEmpty a -> Gen (NonEmpty (b, a))
genValidSeperateForNE = forall b a. Eq b => Gen b -> NonEmpty a -> Gen (NonEmpty (b, a))
genSeperateForNE forall a. GenValid a => Gen a
genValid

genSeperate :: Ord a => Gen a -> Gen [a]
genSeperate :: forall a. Ord a => Gen a -> Gen [a]
genSeperate Gen a
g = forall a. Ord a => [a] -> [a]
nubOrd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Gen a -> Gen [a]
genListOf Gen a
g

-- TODO these two can likely be optimised
genSeperateFor :: Eq b => Gen b -> [a] -> Gen [(b, a)]
genSeperateFor :: forall b a. Eq b => Gen b -> [a] -> Gen [(b, a)]
genSeperateFor Gen b
_ [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure []
genSeperateFor Gen b
g (a
a : [a]
as) = forall a. NonEmpty a -> [a]
NE.toList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall b a. Eq b => Gen b -> NonEmpty a -> Gen (NonEmpty (b, a))
genSeperateForNE Gen b
g (a
a forall a. a -> [a] -> NonEmpty a
:| [a]
as)

genSeperateForNE :: Eq b => Gen b -> NonEmpty a -> Gen (NonEmpty (b, a))
genSeperateForNE :: forall b a. Eq b => Gen b -> NonEmpty a -> Gen (NonEmpty (b, a))
genSeperateForNE Gen b
g (a
a :| [a]
as) = do
  [(b, a)]
restTups <- forall b a. Eq b => Gen b -> [a] -> Gen [(b, a)]
genSeperateFor Gen b
g [a]
as
  b
b <- Gen b
g forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [(b, a)]
restTups)
  forall (f :: * -> *) a. Applicative f => a -> f a
pure ((b
b, a
a) forall a. a -> [a] -> NonEmpty a
:| [(b, a)]
restTups)