@@ -1,6 +1,44 @@
11module Regression.T5 (test5) where
22
3+import Control.Ether.Abbr
4+
5+import qualified Control.Monad.Ether.Implicit as I
6+import qualified Control.Ether.Implicit.Abbr as I
7+
38import Test.Tasty
9+import Test.Tasty.QuickCheck
10+
11+newtype Counter = Counter Int
12+ deriving (Eq, Ord, Num, Enum)
13+
14+incCounter :: Counter -> Counter
15+incCounter = succ
16+
17+testEther
18+ :: (Num a, Ord a) => Ether '[I.R a, I.S Counter] m
19+ => m a
20+testEther = do
21+ a <- I.ask
22+ if a <= 0
23+ then do
24+ I.put (0 :: Counter)
25+ return 1
26+ else do
27+ I.modify incCounter -- overriden in the base case
28+ b <- I.runReaderT testEther (a - 1)
29+ I.modify incCounter
30+ return (a * b)
31+
32+runner :: (Num a, Ord a) => a -> (a, Counter)
33+runner a = I.runState (I.runReaderT testEther a) (0 :: Counter)
34+
35+factorial :: (Num a, Enum a) => a -> a
36+factorial a = product [1..a]
437
538test5 :: TestTree
6−test5 = testGroup "T5:" []
39+test5 = testGroup "T5: Factorial via Ether"
40+ [ testProperty "runner works"
41+ $ \n -> property
42+ $ let n' = fromIntegral n :: Integer
43+ in runner n' == (factorial n', max 0 (Counter n))
44+ ]