ether-0.4.0.0: test/Regression/T5.hs
module Regression.T5 (test5) where
import Control.Ether.Abbr
import qualified Control.Monad.Ether.Implicit as I
import qualified Control.Ether.Implicit.Abbr as I
import Test.Tasty
import Test.Tasty.QuickCheck
newtype Counter = Counter Int
deriving (Eq, Ord, Num, Enum)
incCounter :: Counter -> Counter
incCounter = succ
testEther
:: (Num a, Ord a)
=> Ether '[I.R a, I.S Counter] m
=> m a
testEther = do
a <- I.ask
if a <= 0
then do
I.put (0 :: Counter)
return 1
else do
I.modify incCounter -- overriden in the base case
b <- I.runReaderT testEther (a - 1)
I.modify incCounter
return (a * b)
runner :: (Num a, Ord a) => a -> (a, Counter)
runner a = I.runState (I.runReaderT testEther a) (0 :: Counter)
factorial :: (Num a, Enum a) => a -> a
factorial a = product [1..a]
test5 :: TestTree
test5 = testGroup "T5: Factorial via Ether"
[ testProperty "runner works"
$ \n -> property
$ let n' = fromIntegral n :: Integer
in runner n' == (factorial n', max 0 (Counter n))
]