packages feed

ether-0.5.0.0: test/Regression/T5.hs

module Regression.T5 (test5) where

import Ether

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)
  => (MonadReader' a m, MonadState' Counter m)
  => m a
testEther = do
  a <- ask'
  if a <= 0
    then do
      put' (0 :: Counter)
      return 1
    else do
      modify' incCounter -- overriden in the base case
      b <- runReaderT' testEther (a - 1)
      modify' incCounter
      return (a * b)

runner :: (Num a, Ord a) => a -> (a, Counter)
runner a = runState' (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))
  ]