quickcheck-quid-0.0.1.1: src/internal/Internal/Test/QuickCheck/Quid/Representations.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Internal.Test.QuickCheck.Quid.Representations
where
import Data.List.NonEmpty
( NonEmpty )
import Data.Proxy
( Proxy (..) )
import Internal.Test.QuickCheck.Quid
( Quid (..) )
import Numeric.Natural
( Natural )
import qualified Data.Foldable as F
import qualified Data.List.NonEmpty as NE
nonEmptyListToQuid :: forall a. (Bounded a, Enum a) => NonEmpty a -> Quid
nonEmptyListToQuid xs = Quid $
F.foldl' f 0 xs - 1
where
f !acc !x = acc * base + 1 + fromIntegral (fromEnum x)
base = fromIntegral @Int @Natural $ boundedEnumCardinality $ Proxy @a
nonEmptyListFromQuid :: forall a. (Bounded a, Enum a) => Quid -> NonEmpty a
nonEmptyListFromQuid (Quid q) =
NE.fromList $ go [] q
where
go :: [a] -> Natural -> [a]
go !acc !n
| n < base =
toEnum (fromIntegral n) : acc
| otherwise =
go (toEnum (fromIntegral (n `mod` base)) : acc) (n `div` base - 1)
base = fromIntegral @Int @Natural $ boundedEnumCardinality $ Proxy @a
boundedEnumCardinality :: forall a. (Bounded a, Enum a) => Proxy a -> Int
boundedEnumCardinality _ = fromEnum (maxBound @a) - fromEnum (minBound @a) + 1