{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

module Test.QuickCheck.SafeGen.Generic
  ( SafeArbitrary (..),
    FromSafeArbitrary (..),
  )
where

import Control.Applicative (liftA2)
import qualified Control.Applicative
import Data.Coerce
import qualified Data.Complex
import Data.List.NonEmpty (NonEmpty)
import qualified Data.Monoid
import qualified Data.Ratio
import qualified Foreign
import qualified Foreign.C
import GHC.Generics
import Test.QuickCheck.Arbitrary
import qualified Test.QuickCheck.Modifiers
import Test.QuickCheck.SafeGen.Internal
import qualified Data.Functor.Identity as Data.Functor

-- | Like 'Arbitrary', but with 'SafeGen' instead of 'Gen'.
-- In practice, you probably won't interface with this class directly other than deriving an instance when deriving 'Arbitrary' via 'FromSafeArbitrary'.
--
-- One exception might be when you're not happy with the way 'FromSafeArbitrary' derives 'shrink', and you want to manually implement it.
-- In that case, you can manually write @'arbitrary' = 'runSafeGen' 'safeArbitrary'@
--
-- Another example is when working with lazy infinite data, in which case you might want to remove the termination check using @'arbitrary' = 'runSafeGenNoCheck' 'safeArbitrary'@.
class SafeArbitrary a where
  safeArbitrary :: SafeGen a
  default safeArbitrary :: (Generic a, GSafeArbitrary (Rep a)) => SafeGen a
  safeArbitrary = forall a x. Generic a => Rep a x -> a
to forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (a :: * -> *) x. GSafeArbitrary a => SafeGen (a x)
gsafeArbitrary

class GSafeArbitrary a where
  gsafeArbitrary :: SafeGen (a x)

class GSafeArbitrarySum a where
  gsafeArbitrarySum :: NonEmpty (Int, SafeGen (a x))

-- | Intended to be used as a deriving conduit for 'Arbitrary' from 'SafeArbitrary'.
-- This defines 'arbitrary' as @'runSafeGen' 'arbitrary'@, and 'shrink' as 'genericShrink'.
newtype FromSafeArbitrary a = FromSafeArbitrary a

instance
  ( Generic a,
    SafeArbitrary a,
    RecursivelyShrink (Rep a),
    GSubterms (Rep a) a
  ) =>
  Arbitrary (FromSafeArbitrary a)
  where
  arbitrary :: Gen (FromSafeArbitrary a)
arbitrary = forall a. a -> FromSafeArbitrary a
FromSafeArbitrary forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. SafeGen a -> Gen a
runSafeGen forall a. SafeArbitrary a => SafeGen a
safeArbitrary
  shrink :: FromSafeArbitrary a -> [FromSafeArbitrary a]
shrink (FromSafeArbitrary a
a) = forall a. a -> FromSafeArbitrary a
FromSafeArbitrary forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a.
(Generic a, RecursivelyShrink (Rep a), GSubterms (Rep a) a) =>
a -> [a]
genericShrink a
a

instance GSafeArbitrarySum f => GSafeArbitrary (M1 D c f) where
  gsafeArbitrary :: forall x. SafeGen (M1 D c f x)
  gsafeArbitrary :: forall x. SafeGen (M1 D c f x)
gsafeArbitrary = forall a. NonEmpty (Int, SafeGen a) -> SafeGen a
Choice forall a b. (a -> b) -> a -> b
$ coerce :: forall a b. Coercible a b => a -> b
coerce (forall (a :: * -> *) x.
GSafeArbitrarySum a =>
NonEmpty (Int, SafeGen (a x))
gsafeArbitrarySum :: NonEmpty (Int, SafeGen (f x)))

instance (GSafeArbitrarySum f, GSafeArbitrarySum g) => GSafeArbitrarySum (f :+: g) where
  gsafeArbitrarySum :: forall x. NonEmpty (Int, SafeGen ((f :+: g) x))
  gsafeArbitrarySum :: forall x. NonEmpty (Int, SafeGen ((:+:) f g x))
gsafeArbitrarySum = (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 forall (a :: * -> *) x.
GSafeArbitrarySum a =>
NonEmpty (Int, SafeGen (a x))
gsafeArbitrarySum forall a. Semigroup a => a -> a -> a
<> (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 forall (a :: * -> *) x.
GSafeArbitrarySum a =>
NonEmpty (Int, SafeGen (a x))
gsafeArbitrarySum

instance GSafeArbitrary f => GSafeArbitrarySum (M1 C c f) where
  gsafeArbitrarySum :: forall x. NonEmpty (Int, SafeGen (M1 C c f x))
gsafeArbitrarySum = forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
1, forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (a :: * -> *) x. GSafeArbitrary a => SafeGen (a x)
gsafeArbitrary)

instance GSafeArbitrary f => GSafeArbitrary (M1 S c f) where
  gsafeArbitrary :: forall x. SafeGen (M1 S c f x)
gsafeArbitrary = forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (a :: * -> *) x. GSafeArbitrary a => SafeGen (a x)
gsafeArbitrary

instance (GSafeArbitrary f, GSafeArbitrary g) => GSafeArbitrary (f :*: g) where
  gsafeArbitrary :: forall x. SafeGen ((:*:) f g x)
gsafeArbitrary = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
(:*:) forall (a :: * -> *) x. GSafeArbitrary a => SafeGen (a x)
gsafeArbitrary forall (a :: * -> *) x. GSafeArbitrary a => SafeGen (a x)
gsafeArbitrary

instance (SafeArbitrary a) => GSafeArbitrary (K1 i a) where
  gsafeArbitrary :: forall x. SafeGen (K1 i a x)
gsafeArbitrary = forall k i c (p :: k). c -> K1 i c p
K1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. SafeArbitrary a => SafeGen a
safeArbitrary

instance GSafeArbitrary U1 where gsafeArbitrary :: forall x. SafeGen (U1 x)
gsafeArbitrary = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall k (p :: k). U1 p
U1

instance SafeArbitrary a => SafeArbitrary (Maybe a) where
  safeArbitrary :: SafeGen (Maybe a)
safeArbitrary = forall a. [(Int, SafeGen a)] -> SafeGen a
frequency [(Int
1, forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing), (Int
3, forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. SafeArbitrary a => SafeGen a
safeArbitrary)]

instance SafeArbitrary a => SafeArbitrary [a] where
  safeArbitrary :: SafeGen [a]
safeArbitrary = forall a. [(Int, SafeGen a)] -> SafeGen a
frequency [(Int
1, forall (f :: * -> *) a. Applicative f => a -> f a
pure []), (Int
3, forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (:) forall a. SafeArbitrary a => SafeGen a
safeArbitrary forall a. SafeArbitrary a => SafeGen a
safeArbitrary)]

{- ORMOLU_DISABLE -}

instance SafeArbitrary a => SafeArbitrary (NonEmpty a)
instance (SafeArbitrary a, SafeArbitrary b) => SafeArbitrary (Either a b)

instance (SafeArbitrary a, SafeArbitrary b) => SafeArbitrary (a, b)
instance (SafeArbitrary a, SafeArbitrary b, SafeArbitrary c) => SafeArbitrary (a, b, c)
instance (SafeArbitrary a, SafeArbitrary b, SafeArbitrary c, SafeArbitrary d) => SafeArbitrary (a, b, c, d)
instance (SafeArbitrary a, SafeArbitrary b, SafeArbitrary c, SafeArbitrary d, SafeArbitrary e) => SafeArbitrary (a, b, c, d, e)

instance SafeArbitrary Bool

instance SafeArbitrary Char   where safeArbitrary :: SafeGen Char
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Double where safeArbitrary :: SafeGen Double
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Float  where safeArbitrary :: SafeGen Float
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb

instance SafeArbitrary Integer where safeArbitrary :: SafeGen Integer
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Ordering
instance SafeArbitrary ()

instance SafeArbitrary Int            where safeArbitrary :: SafeGen Int
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Int8   where safeArbitrary :: SafeGen Int8
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Int16  where safeArbitrary :: SafeGen Int16
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Int32  where safeArbitrary :: SafeGen Int32
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Int64  where safeArbitrary :: SafeGen Int64
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Word   where safeArbitrary :: SafeGen Word
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Word8  where safeArbitrary :: SafeGen Word8
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Word16 where safeArbitrary :: SafeGen Word16
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Word32 where safeArbitrary :: SafeGen Word32
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.Word64 where safeArbitrary :: SafeGen Word64
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb

instance Integral a      => SafeArbitrary (Data.Ratio.Ratio a) where safeArbitrary :: SafeGen (Ratio a)
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary a => SafeArbitrary (Data.Complex.Complex a)

deriving newtype instance SafeArbitrary a => SafeArbitrary (Control.Applicative.ZipList a)
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Functor.Identity a)

deriving newtype instance                    SafeArbitrary Data.Monoid.All
deriving newtype instance                    SafeArbitrary Data.Monoid.Any
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Monoid.First a)
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Monoid.Last a)
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Monoid.Dual a)
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Monoid.Sum a)
deriving newtype instance SafeArbitrary a => SafeArbitrary (Data.Monoid.Product a)

instance SafeArbitrary Foreign.C.CChar      where safeArbitrary :: SafeGen CChar
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CSChar     where safeArbitrary :: SafeGen CSChar
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUChar     where safeArbitrary :: SafeGen CUChar
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CShort     where safeArbitrary :: SafeGen CShort
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUShort    where safeArbitrary :: SafeGen CUShort
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CInt       where safeArbitrary :: SafeGen CInt
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUInt      where safeArbitrary :: SafeGen CUInt
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CLong      where safeArbitrary :: SafeGen CLong
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CULong     where safeArbitrary :: SafeGen CULong
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CLLong     where safeArbitrary :: SafeGen CLLong
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CULLong    where safeArbitrary :: SafeGen CULLong
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CFloat     where safeArbitrary :: SafeGen CFloat
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CDouble    where safeArbitrary :: SafeGen CDouble
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CPtrdiff   where safeArbitrary :: SafeGen CPtrdiff
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CSize      where safeArbitrary :: SafeGen CSize
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CWchar     where safeArbitrary :: SafeGen CWchar
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CSigAtomic where safeArbitrary :: SafeGen CSigAtomic
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CClock     where safeArbitrary :: SafeGen CClock
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CTime      where safeArbitrary :: SafeGen CTime
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUSeconds  where safeArbitrary :: SafeGen CUSeconds
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CSUSeconds where safeArbitrary :: SafeGen CSUSeconds
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CIntPtr    where safeArbitrary :: SafeGen CIntPtr
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUIntPtr   where safeArbitrary :: SafeGen CUIntPtr
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CIntMax    where safeArbitrary :: SafeGen CIntMax
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Foreign.C.CUIntMax   where safeArbitrary :: SafeGen CUIntMax
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb

instance SafeArbitrary Test.QuickCheck.Modifiers.PrintableString where safeArbitrary :: SafeGen PrintableString
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb
instance SafeArbitrary Test.QuickCheck.Modifiers.UnicodeString   where safeArbitrary :: SafeGen UnicodeString
safeArbitrary = forall a. Arbitrary a => SafeGen a
arb