{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} {-# HLINT ignore "Eta reduce" #-} module Reader ( tests , gen0 , genN , test ) where import qualified Control.Carrier.Reader as ReaderC import Control.Effect.Reader import qualified Control.Monad.Trans.Reader as ReaderT import qualified Control.Monad.Trans.RWS.Lazy as LazyRWST import qualified Control.Monad.Trans.RWS.Strict as StrictRWST import Data.Function ((&)) import Gen import GHC.Generics ((:.:)(..)) import qualified Monad import qualified MonadFix import Test.Tasty import Test.Tasty.Hedgehog tests :: TestTree tests = testGroup "Reader" [ testGroup "ReaderC" $ [ testMonad , testMonadFix , testReader ] >>= ($ runR (uncurry ReaderC.runReader . lower)) , testGroup "(->)" $ testReader (runR (uncurry (fmap pure . (&)) . lower)) , testGroup "ReaderT" $ testReader (runR (uncurry (flip ReaderT.runReaderT) . lower)) , testGroup "RWST (Lazy)" $ testReader (runR (uncurry (runRWST LazyRWST.runRWST) . lower)) , testGroup "RWST (Strict)" $ testReader (runR (uncurry (runRWST StrictRWST.runRWST) . lower)) ] where testMonad run = Monad.test (m (gen0 r) (genN r)) a b c (Comp1 <$> (identity <*> (pair <*> r <*> unit))) run testMonadFix run = MonadFix.test (m (gen0 r) (genN r)) a b (Comp1 <$> (identity <*> (pair <*> r <*> unit))) run testReader run = Reader.test r (m (gen0 r) (genN r)) a (identity <*> unit) run runRWST f r m = (\ (a, _, ()) -> a) <$> f m r r lower = runIdentity . unComp1 gen0 :: forall r m a sig . (Has (Reader r) sig m, Arg r, Show r, Vary r) => GenTerm r -> GenTerm a -> [GenTerm (m a)] gen0 _ a = [ label "asks" (asks @r) <*> fn a ] genN :: (Has (Reader r) sig m, Arg r, Show r, Vary r) => GenTerm r -> GenM m -> GenTerm a -> [GenTerm (m a)] genN r m a = [ subtermM (m a) (label "local" local <*> fn r <*>) ] test :: (Has (Reader r) sig m, Arg r, Eq a, Show a, Show r, Vary r, Functor f) => GenTerm r -> GenM m -> GenTerm a -> GenTerm (f ()) -> Run (f :.: (,) r) Identity m -> [TestTree] test r m a i (Run runReader) = [ testProperty "ask returns the environment variable" . forall (i :. r :. fn (m a) :. Nil) $ \ i r k -> runReader (Comp1 ((r, ask >>= k) <$ i)) === runReader (Comp1 ((r, k r) <$ i)) , testProperty "local modifies the environment variable" . forall (i :. r :. fn r :. m a :. Nil) $ \ i r f m -> runReader (Comp1 ((r, local f m) <$ i)) === runReader (Comp1 ((f r, m) <$ i)) ]