proarrow-0.1.0.0: test/Props/Simplex.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Props.Simplex where
import Data.Falsify.ConcreteFun qualified as ConcreteFun
import Data.Fin (Fin (..), absurd, isMin)
import Data.Foldable (Foldable (..), toList)
import Data.Monoid (All (..), Ap (..))
import Data.Vec.Lazy (Vec (..), universe, zipWith)
import Data.Void qualified as Void
import Test.Falsify.Generator (Function (..), choose)
import Test.Tasty (TestTree, testGroup)
import Prelude hiding (fst, id, snd, zipWith)
import Proarrow.Category.Instance.Simplex (Forget, IsNat (..), Nat (..), Pick, SNat (..), Simplex (..))
import Proarrow.Core (Ob)
import Proarrow.Profunctor.Representable (Rep)
import Proarrow.Testing
( GenTotal (..)
, ShowP (..)
, Testable (..)
, TestableProfunctor
, TestableType (..)
, TestingEqShow (..)
, genSomeDef
, oneElem
, optGen
, pattern GenNonEmpty
)
import Proarrow.Testing.Laws
import Props.Hask ()
test :: TestTree
test =
testGroup
"Simplex"
[ testCategory @Nat
, testInitialObject @Nat
, testTerminalObject @Nat
, testMonoidal_ @Nat
, testMonoid_ @Z
, testMonoid_ @(S Z)
, testProfunctor @(Rep Forget)
, testProfunctor @(Rep (Pick Bool))
]
instance Testable Nat where
type TestOb a = Ob a
genSome = genSomeDef @'[Z, S Z, S (S Z), S (S (S Z))]
showOb @a = show (singNat @a)
instance (Ob a, Ob b) => TestingEqShow (Simplex a b)
instance (Ob a, Ob b) => TestableType (Simplex a b) where
gen = case (singNat @a, singNat @b) of
(SZ, SZ) -> oneElem ZZ
(SZ, SS @b') -> case gen @(Simplex Z b') of
GenEmpty f -> GenEmpty (\(Y p) -> f p)
GenNonEmpty gf -> GenNonEmpty (Y <$> gf)
(SS, SZ) -> GenEmpty \case {}
(SS @a', SS @b') -> case (gen @(Simplex a' b), gen @(Simplex (S a') b')) of
(GenEmpty l, GenEmpty r) -> GenEmpty \case
X f -> l f
Y f -> r f
(GenNonEmpty gf, GenEmpty _) -> GenNonEmpty (X <$> gf)
(GenEmpty _, GenNonEmpty gg) -> GenNonEmpty (Y <$> gg)
(GenNonEmpty gf, GenNonEmpty gg) -> GenNonEmpty (choose (X <$> gf) (Y <$> gg))
instance TestableProfunctor Simplex
instance (IsNat n) => TestingEqShow (Fin n)
instance (IsNat n) => TestableType (Fin n) where
gen = case singNat @n of
SZ -> GenEmpty absurd
_ -> optGen (toList universe)
instance (IsNat n) => Function (Fin n) where
function = case singNat @n of
SZ -> fmap (ConcreteFun.map absurd Void.absurd) . function @Void.Void
SS @m -> fmap (ConcreteFun.map isMin (maybe FZ FS)) . function @(Maybe (Fin m))
instance (TestableType a, IsNat n) => TestableType (Vec n a) where
gen = case gen @a of
GenEmpty ax -> case universe @n of VNil -> oneElem VNil; _ -> GenEmpty \(a ::: _) -> ax a
GenNonEmpty ga -> GenNonEmpty (traverse (const ga) universe)
instance (TestingEqShow a, IsNat n) => TestingEqShow (Vec n a) where
eqP VNil VNil = pure True
eqP as bs = getAll <$> getAp (fold (zipWith (\l r -> Ap (fmap All (eqP l r))) as bs))
showP = show . fmap ShowP
instance (IsNat n, Function a) => Function (Vec n a) where
function = case singNat @n of
SZ -> fmap (ConcreteFun.map (\VNil -> ()) (\() -> VNil)) . function @()
SS @m -> fmap (ConcreteFun.map (\(x ::: xs) -> (x, xs)) (uncurry (:::))) . function @(a, Vec m a)
instance TestableProfunctor (Rep Forget)
instance TestableProfunctor (Rep (Pick Bool))