proarrow-0.1.0.0: test/Props/Span.hs
{-# LANGUAGE OverloadedLists #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Props.Span where
import Data.Foldable (toList)
import Data.Typeable ((:~:) (..))
import Test.Tasty (TestTree, testGroup)
import Prelude (Bool (..), Maybe (..), pure, zip, ($), (&&), (++), (<$>), (<*>), (==), (||))
import Proarrow.Category.Instance.FinSet (FINSET (..), unFinSet)
import Proarrow.Category.Instance.Span (SPAN (..), Span (..))
import Proarrow.Core (CAT, CategoryOf (..), UN, (//), (\\))
import Data.List (sort)
import Proarrow.Testing
( GenTotal (..)
, Some (..)
, Testable (..)
, TestableProfunctor
, TestableType (..)
, TestingEqShow (..)
, mapSome
, pattern GenNonEmpty
)
import Proarrow.Testing.Laws
import Props.FinSet (eqFinSet)
test :: TestTree
test =
testGroup
"Span(FinSet)"
[ testCategory @(SPAN FINSET)
, testDagger @(SPAN FINSET)
, testMonoidal_ @(SPAN FINSET)
, testSymMonoidal_ @(SPAN FINSET)
, testClosed_ @(SPAN FINSET)
, testStarAutonomous_ @(SPAN FINSET)
, testCompactClosed_ @(SPAN FINSET)
, testCopyDiscard_ @(SPAN FINSET)
, testHypergraph_ @(SPAN FINSET)
]
-- instance (Testable k, HasPushouts k, TestObIsOb k) => Testable (SPAN k) where
instance Testable (SPAN FINSET) where
type TestOb a = Ob a
showOb @a = showOb @_ @(UN SP a)
genSome = mapSome SP <$> genSome
genSomeSmall = mapSome SP <$> genSomeSmall
-- instance (Ob a, Ob b, Testable k, TestObIsOb k) => TestingEqShow (Span a (b :: SPAN k)) where
instance (Ob a, Ob b) => TestingEqShow (Span a (b :: SPAN FINSET)) where
eqP (Span @c1 l1 r1) (Span @c2 l2 r2) =
l1 //
l2 //
case eqFinSet @c1 @c2 of
Just Refl -> do
eql <- eqP l1 l2
eqr <- eqP r1 r2
-- Both legs map out of the apex, so any relabelling of it is admissible. Two spans
-- are isomorphic exactly when their multisets of (left, right) image pairs agree.
-- Cospan's legs map in, so it has to search instead (see "Props.Cospan").
let hasIso = sort (zip (toList (unFinSet l1)) (toList (unFinSet r1))) == sort (zip (toList (unFinSet l2)) (toList (unFinSet r2)))
pure $ (eql && eqr) || hasIso
Nothing -> pure False
showP (Span @c l r) = "Span @(" ++ showOb @_ @c ++ ") (" ++ showP l ++ ") (" ++ showP r ++ ")" \\ l
-- instance (TestOb a, TestOb b, Testable k, TestObIsOb k) => TestableType (Span a (b :: SPAN k)) where
instance (TestOb a, TestOb b) => TestableType (Span a (b :: SPAN FINSET)) where
gen = GenNonEmpty loop
where
loop = do
Some @c <- genSome @_
case (gen @(c ~> UN SP a), gen @(c ~> UN SP b)) of
(GenEmpty _, _) -> loop
(_, GenEmpty _) -> loop
(GenNonEmpty l, GenNonEmpty r) -> Span <$> l <*> r
instance TestableProfunctor (Span :: CAT (SPAN FINSET))