{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Test.Util.Slots (NumSlots (..)) where

import           Data.Word (Word64)
import           GHC.Generics (Generic)
import           NoThunks.Class (NoThunks)
import           Quiet (Quiet (..))
import qualified Test.QuickCheck as QC
import           Test.QuickCheck (Arbitrary (..))

-- | Number of slots
newtype NumSlots = NumSlots {NumSlots -> Word64
unNumSlots :: Word64}
  deriving (NumSlots -> NumSlots -> Bool
(NumSlots -> NumSlots -> Bool)
-> (NumSlots -> NumSlots -> Bool) -> Eq NumSlots
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NumSlots -> NumSlots -> Bool
== :: NumSlots -> NumSlots -> Bool
$c/= :: NumSlots -> NumSlots -> Bool
/= :: NumSlots -> NumSlots -> Bool
Eq, (forall x. NumSlots -> Rep NumSlots x)
-> (forall x. Rep NumSlots x -> NumSlots) -> Generic NumSlots
forall x. Rep NumSlots x -> NumSlots
forall x. NumSlots -> Rep NumSlots x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. NumSlots -> Rep NumSlots x
from :: forall x. NumSlots -> Rep NumSlots x
$cto :: forall x. Rep NumSlots x -> NumSlots
to :: forall x. Rep NumSlots x -> NumSlots
Generic, Context -> NumSlots -> IO (Maybe ThunkInfo)
Proxy NumSlots -> String
(Context -> NumSlots -> IO (Maybe ThunkInfo))
-> (Context -> NumSlots -> IO (Maybe ThunkInfo))
-> (Proxy NumSlots -> String)
-> NoThunks NumSlots
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
$cnoThunks :: Context -> NumSlots -> IO (Maybe ThunkInfo)
noThunks :: Context -> NumSlots -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> NumSlots -> IO (Maybe ThunkInfo)
wNoThunks :: Context -> NumSlots -> IO (Maybe ThunkInfo)
$cshowTypeOf :: Proxy NumSlots -> String
showTypeOf :: Proxy NumSlots -> String
NoThunks)
  deriving (Int -> NumSlots -> ShowS
[NumSlots] -> ShowS
NumSlots -> String
(Int -> NumSlots -> ShowS)
-> (NumSlots -> String) -> ([NumSlots] -> ShowS) -> Show NumSlots
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NumSlots -> ShowS
showsPrec :: Int -> NumSlots -> ShowS
$cshow :: NumSlots -> String
show :: NumSlots -> String
$cshowList :: [NumSlots] -> ShowS
showList :: [NumSlots] -> ShowS
Show) via (Quiet NumSlots)

{-------------------------------------------------------------------------------
  Arbitrary instances
-------------------------------------------------------------------------------}

-- TODO: We shouldn't really pick the number of slots independent from k
instance Arbitrary NumSlots where
  arbitrary :: Gen NumSlots
arbitrary = Word64 -> NumSlots
NumSlots (Word64 -> NumSlots) -> Gen Word64 -> Gen NumSlots
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word64, Word64) -> Gen Word64
forall a. Random a => (a, a) -> Gen a
QC.choose (Word64
minNumSlots, Word64
100)
  shrink :: NumSlots -> [NumSlots]
shrink (NumSlots Word64
n) = Word64 -> NumSlots
NumSlots (Word64 -> NumSlots) -> [Word64] -> [NumSlots]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Word64 -> Bool) -> [Word64] -> [Word64]
forall a. (a -> Bool) -> [a] -> [a]
filter (Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word64
minNumSlots) ([Word64] -> [Word64]) -> [Word64] -> [Word64]
forall a b. (a -> b) -> a -> b
$ Word64 -> [Word64]
forall a. Arbitrary a => a -> [a]
shrink Word64
n)

minNumSlots :: Word64
minNumSlots :: Word64
minNumSlots = Word64
1