{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} {-# HLINT ignore "Eta reduce" #-} module Cut ( tests , gen0 , genN , test ) where import qualified Control.Carrier.Cut.Church as CutC import Control.Carrier.Reader import Control.Effect.Choose import Control.Effect.Cut (Cut, call, cutfail) import Control.Effect.NonDet (NonDet) import Data.Semigroup as S ((<>)) import Gen import qualified Monad import qualified MonadFix import qualified NonDet import qualified Reader import Test.Tasty import Test.Tasty.Hedgehog tests :: TestTree tests = testGroup "Cut" [ testGroup "CutC" $ [ testMonad , testMonadFix , testCut ] >>= ($ runL CutC.runCutA) , testGroup "ReaderC · CutC" $ Cut.test (local (id @R)) (m (gen0 S.<> Reader.gen0 r) (\ m -> genN m S.<> Reader.genN r m)) a b (pair <*> r <*> unit) (Run (CutC.runCutA . uncurry runReader)) , testGroup "CutC · ReaderC" $ Cut.test (local (id @R)) (m (gen0 S.<> Reader.gen0 r) (\ m -> genN m S.<> Reader.genN r m)) a b (pair <*> r <*> unit) (Run (uncurry ((. CutC.runCutA) . runReader))) ] where testMonad run = Monad.test (m gen0 genN) a b c initial run testMonadFix run = MonadFix.test (m gen0 genN) a b initial run testCut run = Cut.test id (m gen0 genN) a b initial run initial = identity <*> unit gen0 :: (Has Cut sig m, Has NonDet sig m) => GenTerm a -> [GenTerm (m a)] gen0 a = label "cutfail" cutfail : NonDet.gen0 a genN :: (Has Cut sig m, Has NonDet sig m) => GenM m -> GenTerm a -> [GenTerm (m a)] genN m a = subtermM (m a) (label "call" call <*>) : NonDet.genN m a test :: forall a b m f sig . (Has Cut sig m, Has NonDet sig m, Arg a, Eq a, Eq b, Show a, Show b, Vary a, Functor f) => (forall a . m a -> m a) -> GenM m -> GenTerm a -> GenTerm b -> GenTerm (f ()) -> Run f [] m -> [TestTree] test hom m = (\ a _ i (Run runCut) -> [ testProperty "cutfail annihilates >>=" (forall (i :. fn @a (m a) :. Nil) (\ i k -> runCut ((hom cutfail >>= k) <$ i) === runCut (hom cutfail <$ i))) , testProperty "cutfail annihilates <|>" (forall (i :. m a :. Nil) (\ i m -> runCut ((hom cutfail <|> m) <$ i) === runCut (hom cutfail <$ i))) , testProperty "call delimits cutfail" (forall (i :. m a :. Nil) (\ i m -> runCut ((hom (call (hom cutfail)) <|> m) <$ i) === runCut (m <$ i))) ]) S.<> NonDet.test m