content: {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE NoMonomorphismRestriction #-}
  {-# LANGUAGE TemplateHaskell #-}
  
  module Control.Eff.Logic.Test where
  
  import Test.HUnit hiding (State)
  import Control.Eff.Logic.Core
  import Control.Monad
  
  -- the inferred signature of testCut is insightful
  testCut runChoice =
    let cases = [tcut1, tcut2, tcut3, tcut4, tcut5, tcut6, tcut7, tcut8
                , tcut9]
        runCall = runChoice . call
    in
      forM_ cases $ \(test, result) ->
                      assertEqual "Cut: tcut" result (runCall test)
    where
      -- signature is inferred
      -- tcut1 :: (Member Choose r, Member (Exc CutFalse) r) => Eff r Int
      tc1 = (return (1::Int) `mplus` return 2) `mplus`
            ((cutfalse `mplus` return 4) `mplus`
              return 5)
      rc1 = [1,2]
      tcut1 = (tc1, rc1)
      -- Here we see nested call. It poses no problems...
      tc2 = return (1::Int) `mplus`
            call (return 2 `mplus` (cutfalse `mplus` return 3) `mplus`
                   return 4)
            `mplus` return 5
      rc2 = [1,2,5]
      tcut2 = (tc2, rc2)
      tcut3 = ((call tc1 `mplus` call (tc2 `mplus` cutfalse))
              , rc1 ++ rc2)
      tcut4 = ((call tc1 `mplus`  (tc2 `mplus` cutfalse))
              , rc1 ++ rc2)
      tcut5 = ((call tc1 `mplus`  (cutfalse `mplus` tc2))
              , rc1)
      tcut6 = ((call tc1 `mplus` call (cutfalse `mplus` tc2))
              , rc1)
      tcut7 = ((call tc1 `mplus`  (cutfalse `mplus` tc2) `mplus` tc2)
              , rc1)
      tcut8 = ((call tc1 `mplus` call (cutfalse `mplus` tc2) `mplus` tc2)
              , rc1 ++ rc2)
      incrOrDecr = \x -> (return $! x + 1)
                         `mplus` cutfalse
                         `mplus` (return $! x - 1)
      tc9 = tc1 >>= incrOrDecr
      rc9 = [2]
      tcut9 = (tc9, rc9)
      -- tcut10 = ((return rc1 >>= incrOrDecr)
      --          , rc9)
  