packages feed

extensible-effects 2.0.1.0 → 2.1.0.0

raw patch · 41 files changed

+1527/−1132 lines, 41 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Control.Eff.Choose: instance Data.OpenUnion.Member Control.Eff.Choose.Choose r => GHC.Base.Alternative (Control.Eff.Eff r)
+ Control.Eff.Choose: instance Data.OpenUnion.Member Control.Eff.Choose.Choose r => GHC.Base.MonadPlus (Control.Eff.Eff r)
+ Control.Eff.Example: TooBig :: Int -> TooBig
+ Control.Eff.Example: instance GHC.Classes.Eq Control.Eff.Example.TooBig
+ Control.Eff.Example: instance GHC.Show.Show Control.Eff.Example.TooBig
+ Control.Eff.Example: newtype TooBig
+ Control.Eff.Example: runErrBig :: Eff (Exc TooBig : r) a -> Eff r (Either TooBig a)
+ Control.Eff.Lift: catchDynE :: forall e a r. (SetMember Lift (Lift IO) r, Exception e) => Eff r a -> (e -> Eff r a) -> Eff r a

Files

README.md view
@@ -14,9 +14,15 @@   * Effects can be added, removed, and interwoven without changes to code not     dealing with those effects. -## Disadvantages+## Limitations  ### Current implementation only supports GHC version 7.8 and above+This is not a fundamental limitation of the design or the approach, but there is+an overhead with making the code compatible across a large number of GHC+versions. If this is needed, patches are welcome :)++## Disadvantages+ ### Ambiguity-Flexibility tradeoff   * The extensibility comes at the cost of some ambiguity. Note, however, that     the extensibility can be traded back, but that detracts from some of the
extensible-effects.cabal view
@@ -6,7 +6,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             2.0.1.0+version:             2.1.0.0  -- A short (one-line) description of the package. synopsis:            An Alternative to Monad Transformers@@ -75,16 +75,16 @@                        Control.Eff.Fresh                        Control.Eff.Lift                        Control.Eff.NdetEff+                       Control.Eff.Operational+                       Control.Eff.Operational.Example                        Control.Eff.Reader.Lazy                        Control.Eff.Reader.Strict                        Control.Eff.State.LazyState                        Control.Eff.State.Lazy                        Control.Eff.State.Strict+                       Control.Eff.Trace                        Control.Eff.Writer.Lazy                        Control.Eff.Writer.Strict-                       Control.Eff.Trace-                       Control.Eff.Operational-                       Control.Eff.Operational.Example                        Data.OpenUnion    -- Modules included in this library but not exported.@@ -143,6 +143,25 @@   type: exitcode-stdio-1.0   main-is: Test.hs   hs-source-dirs: test/+  other-modules:  Utils+                , Control.Eff.Test+                , Control.Eff.Choose.Test+                , Control.Eff.Coroutine.Test+                , Control.Eff.Cut.Test+                , Control.Eff.Example.Test+                , Control.Eff.Exception.Test+                , Control.Eff.Fresh.Test+                , Control.Eff.Lift.Test+                , Control.Eff.NdetEff.Test+                , Control.Eff.Operational.Test+                , Control.Eff.Reader.Lazy.Test+                , Control.Eff.Reader.Strict.Test+                , Control.Eff.State.Lazy.Test+                , Control.Eff.State.LazyState.Test+                , Control.Eff.State.Strict.Test+                , Control.Eff.Trace.Test+                , Control.Eff.Writer.Lazy.Test+                , Control.Eff.Writer.Strict.Test    ghc-options: -Wall 
src/Control/Eff.hs view
@@ -20,7 +20,10 @@ -- Extensible Effects are implemented as typeclass constraints on an Eff[ect] datatype. -- A contrived example can be found under "Control.Eff.Example". To run the -- effects, consult the tests.-module Control.Eff where+module Control.Eff (+  module Control.Eff+  , module Data.OpenUnion+  ) where  #if __GLASGOW_HASKELL__ < 710 import Control.Applicative
src/Control/Eff/Choose.hs view
@@ -1,9 +1,11 @@+{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Safe #-}+{-# LANGUAGE CPP #-} -- The following is needed to define MonadPlus instance. It is decidable -- (there is no recursion!), but GHC cannot see that. {-# LANGUAGE UndecidableInstances #-}@@ -17,7 +19,10 @@                           ) where  import Control.Eff-import Data.OpenUnion+#if __GLASGOW_HASKELL__ > 708+import Control.Applicative+import Control.Monad+#endif  -- ------------------------------------------------------------------------ -- | Non-determinism (choice)@@ -42,15 +47,16 @@ mplus' :: Member Choose r => Eff r a -> Eff r a -> Eff r a mplus' m1 m2 = choose [m1,m2] >>= id --- FIXME: find a way to uncomment--- -- MonadPlus-like operators are expressible via choose--- instance Member Choose r => Alternative (Eff r) where---   empty     = choose []---   m1 <|> m2 = choose [m1,m2] >>= id+#if __GLASGOW_HASKELL__ > 708+-- | MonadPlus-like operators are expressible via choose+instance Member Choose r => Alternative (Eff r) where+  empty = mzero'+  (<|>) = mplus' --- instance Member Choose r => MonadPlus (Eff r) where---   mzero = empty---   mplus = (<|>)+instance Member Choose r => MonadPlus (Eff r) where+  mzero = empty+  mplus = (<|>)+#endif  -- | Run a nondeterministic effect, returning all values. makeChoice :: forall a r. Eff (Choose ': r) a -> Eff r [a]
src/Control/Eff/Coroutine.hs view
@@ -11,7 +11,6 @@                             ) where  import Control.Eff-import Data.OpenUnion  -- ------------------------------------------------------------------------ -- | Co-routines
src/Control/Eff/Cut.hs view
@@ -43,7 +43,6 @@ import Control.Eff import Control.Eff.Exception import Control.Eff.Choose-import Data.OpenUnion  data CutFalse = CutFalse 
src/Control/Eff/Example.hs view
@@ -3,15 +3,25 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE Safe #-} --- | Example usage of "Control.Eff1"+-- | Example usage of "Control.Eff" module Control.Eff.Example where  import Control.Eff-import Data.OpenUnion+import Control.Eff.Exception  import Control.Eff.State.Lazy import Control.Eff.Writer.Lazy +  -- {{{ TooBig++-- | The datatype for the example from the paper. See the tests for the example+newtype TooBig = TooBig Int deriving (Eq, Show)++-- | specialization to tell the type of the exception+runErrBig :: Eff (Exc TooBig ': r) a -> Eff r (Either TooBig a)+runErrBig = runExc++  -- }}}  -- | Write the elements of a list of numbers, in order. writeAll :: (Member (Writer a) e)
src/Control/Eff/Exception.hs view
@@ -23,7 +23,6 @@  import Control.Eff import Control.Eff.Lift-import Data.OpenUnion  import Control.Monad (void) 
src/Control/Eff/Fresh.hs view
@@ -12,7 +12,6 @@                         ) where  import Control.Eff-import Data.OpenUnion  -- There are three possible implementations -- The first one uses State Fresh where
src/Control/Eff/Lift.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes, ScopedTypeVariables #-} {-# LANGUAGE Safe #-} -- | Lifting primitive Monad types to effectful computations. -- We only allow a single Lifted Monad because Monads aren't commutative@@ -8,10 +8,11 @@ module Control.Eff.Lift ( Lift (..)                        , lift                        , runLift+                       , catchDynE                        ) where  import Control.Eff-import Data.OpenUnion+import qualified Control.Exception as Exc  -- ------------------------------------------------------------------------ -- | Lifting: emulating monad transformers@@ -28,3 +29,17 @@ runLift (E u q) = case prj u of                   Just (Lift m) -> m >>= runLift . qApp q                   Nothing -> error "Impossible: Nothing cannot occur"++-- | Catching of dynamic exceptions+-- See the problem in+-- http://okmij.org/ftp/Haskell/misc.html#catch-MonadIO+catchDynE :: forall e a r.+             (SetMember Lift (Lift IO) r, Exc.Exception e) =>+             Eff r a -> (e -> Eff r a) -> Eff r a+catchDynE m eh = interpose return h m+ where+   -- Polymorphic local binding: signature is needed+   h :: Lift IO v -> Arr r v a -> Eff r a+   h (Lift em) k = lift (Exc.try em) >>= \x -> case x of+         Right x0 -> k x0+         Left  e -> eh e
src/Control/Eff/NdetEff.hs view
@@ -14,7 +14,6 @@ module Control.Eff.NdetEff where  import Control.Eff-import Data.OpenUnion  import Control.Monad import Control.Applicative
src/Control/Eff/Operational.hs view
@@ -19,7 +19,6 @@                                ) where  import Control.Eff-import Data.OpenUnion  -- | Lift values to an effect. -- You can think this is a generalization of @Lift@.
src/Control/Eff/Operational/Example.hs view
@@ -7,8 +7,7 @@ module Control.Eff.Operational.Example where  import Control.Eff.Operational-import Control.Eff (Eff(..))-import Data.OpenUnion+import Control.Eff import Control.Eff.Lift import Control.Eff.Writer.Lazy import Control.Eff.State.Lazy
src/Control/Eff/Reader/Lazy.hs view
@@ -13,7 +13,6 @@                               ) where  import Control.Eff-import Data.OpenUnion  -- ------------------------------------------------------------------------ -- | The Reader monad
src/Control/Eff/Reader/Strict.hs view
@@ -14,7 +14,6 @@                               ) where  import Control.Eff-import Data.OpenUnion  -- ------------------------------------------------------------------------ -- | The Reader monad
src/Control/Eff/State/Lazy.hs view
@@ -13,7 +13,6 @@ import Control.Eff import Control.Eff.Writer.Lazy import Control.Eff.Reader.Lazy-import Data.OpenUnion  -- ------------------------------------------------------------------------ -- | State, lazy (i.e., on-demand)
src/Control/Eff/State/LazyState.hs view
@@ -16,7 +16,6 @@ module Control.Eff.State.LazyState where  import Control.Eff-import Data.OpenUnion  -- | Define a new effect for state on-demand (in ExtEff, the state is -- by default strict -- as it should be if we want the predictable performance
src/Control/Eff/State/Strict.hs view
@@ -14,7 +14,6 @@ import Control.Eff import Control.Eff.Writer.Strict import Control.Eff.Reader.Strict-import Data.OpenUnion  -- ------------------------------------------------------------------------ -- | State, strict
src/Control/Eff/Trace.hs view
@@ -11,7 +11,6 @@                         ) where  import Control.Eff-import Data.OpenUnion  -- | Trace effect for debugging data Trace v where
src/Control/Eff/Writer/Lazy.hs view
@@ -16,7 +16,6 @@                                ) where  import Control.Eff-import Data.OpenUnion  import Data.Monoid import Control.Applicative ((<|>))
src/Control/Eff/Writer/Strict.hs view
@@ -17,7 +17,6 @@                                ) where  import Control.Eff-import Data.OpenUnion  import Data.Monoid import Control.Applicative ((<|>))
+ test/Control/Eff/Choose/Test.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE FlexibleContexts, AllowAmbiguousTypes #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Choose.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Example+import Control.Eff.Example.Test (ex2)+import Control.Eff.Exception+import Control.Eff.Choose+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Choose1_exc11 :: Assertion+case_Choose1_exc11 = [2,3] @=? (run exc11)+  where+    exc11 = makeChoice exc1+    exc1 = return 1 `add` choose [1,2]++case_Choose_ex2 :: Assertion+case_Choose_ex2 =+  let ex2_1 = run . makeChoice . runErrBig $ ex2 (choose [5,7,1])+      ex2_2 = run . runErrBig . makeChoice $ ex2 (choose [5,7,1])+  in+    assertEqual "Choose: Combining exceptions and non-determinism: ex2_1"+    expected1 ex2_1+    >> assertEqual "Choose: Combining exceptions and non-determinism: ex2_2"+    expected2 ex2_2+  where+    expected1 = [Right 5,Left (TooBig 7),Right 1]+    expected2 = Left (TooBig 7)++case_Choose_exRec :: Assertion+case_Choose_exRec =+  let exRec_1 = run . runErrBig . makeChoice $ exRec (ex2 (choose [5,7,1]))+      exRec_2 = run . makeChoice . runErrBig $ exRec (ex2 (choose [5,7,1]))+      exRec_3 = run . runErrBig . makeChoice $ exRec (ex2 (choose [5,7,11,1]))+  in+    assertEqual "Choose: error recovery: exRec_1" expected1 exRec_1+    >> assertEqual "Choose: error recovery: exRec_2" expected2 exRec_2+    >> assertEqual "Choose: error recovery: exRec_1" expected3 exRec_3+  where+    expected1 = Right [5,7,1]+    expected2 = [Right 5,Right 7,Right 1]+    expected3 = Left (TooBig 11)+    -- Errror recovery part+    -- The code is the same as in transf1.hs. The inferred signatures differ+    -- Was: exRec :: MonadError TooBig m => m Int -> m Int+    -- exRec :: Member (Exc TooBig) r => Eff r Int -> Eff r Int+    exRec m = catchExc m handler+      where handler (TooBig n) | n <= 7 = return n+            handler e = throwExc e
+ test/Control/Eff/Coroutine/Test.hs view
@@ -0,0 +1,225 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}++module Control.Eff.Coroutine.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Coroutine+import Control.Eff.Trace+import Control.Eff.Reader.Strict+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++yieldInt :: Member (Yield Int ()) r => Int -> Eff r ()+yieldInt = yield++case_Coroutines_c1 :: Assertion+case_Coroutines_c1 = do+  ((), actual) <- catchOutput c1+  assertEqual+    "Coroutine: Simple coroutines using Eff"+    (unlines ["1", "2", "Done"]) actual+  where+    th1 :: Member (Yield Int ()) r => Eff r ()+    th1 = yieldInt 1 >> yieldInt 2++    c1 = runTrace (loop =<< runC th1)+      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop+            loop (Done)    = trace ("Done")++case_Coroutines_c2 :: Assertion+case_Coroutines_c2 = do+  ((), actual1) <- catchOutput c2+  assertEqual "Coroutine: Add dynamic variables"+    (unlines ["10", "10", "Done"]) actual1+  ((), actual2) <- catchOutput c21+  assertEqual "Coroutine: locally changing the dynamic environment for the suspension"+    (unlines ["10", "11", "Done"]) actual2+  where+    -- The code is essentially the same as that in transf.hs (only added+    -- a type specializtion on yield). The inferred signature is different though.+    -- Before it was+    --    th2 :: MonadReader Int m => CoT Int m ()+    -- Now it is more general:+    th2 :: (Member (Yield Int ()) r, Member (Reader Int) r) => Eff r ()+    th2 = ask >>= yieldInt >> (ask >>= yieldInt)++    -- Code is essentially the same as in transf.hs; no liftIO though+    c2 = runTrace $ runReader (loop =<< runC th2) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop+            loop Done    = trace "Done"++    -- locally changing the dynamic environment for the suspension+    c21 = runTrace $ runReader (loop =<< runC th2) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> local (+(1::Int)) (k ()) >>= loop+            loop Done    = trace "Done"++case_Coroutines_c3 :: Assertion+case_Coroutines_c3 = do+  ((), actual1) <- catchOutput c3+  assertEqual "Coroutine: two sorts of local rebinding"+    (unlines ["10", "10", "20", "20", "Done"]) actual1+  ((), actual2) <- catchOutput c31+  let expected2 = (unlines ["10", "11", "21", "21", "Done"])+  assertEqual "Coroutine: locally changing the dynamic environment for the suspension"+    expected2 actual2+  ((), actual3) <- catchOutput c4+  assertEqual "Coroutine: abstracting the client computation"+    expected2 actual3+  where+    th3 :: (Member (Yield Int ()) r, Member (Reader Int) r) => Eff r ()+    th3 = ay >> ay >> local (+(10::Int)) (ay >> ay)+      where ay = ask >>= yieldInt++    c3 = runTrace $ runReader (loop =<< runC th3) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop+            loop Done    = trace "Done"++    -- The desired result: the coroutine shares the dynamic environment with its+    -- parent; however, when the environment is locally rebound, it becomes+    -- private to coroutine.+    c31 = runTrace $ runReader (loop =<< runC th3) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> local (+(1::Int)) (k ()) >>= loop+            loop Done    = trace "Done"++    -- We now make explicit that the client computation, run by th4,+    -- is abstract. We abstract it out of th4+    c4 = runTrace $ runReader (loop =<< runC (th4 client)) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> local (+(1::Int)) (k ()) >>= loop+            loop Done    = trace "Done"++            -- cl, client, ay are monomorphic bindings+            th4 cl = cl >> local (+(10::Int)) cl+            client = ay >> ay+            ay     = ask >>= yieldInt++case_Corountines_c5 :: Assertion+case_Corountines_c5 = do+  ((), actual) <- catchOutput c5+  let expected = unlines ["10"+                         ,"11"+                         ,"12"+                         ,"18"+                         ,"18"+                         ,"18"+                         ,"29"+                         ,"29"+                         ,"29"+                         ,"29"+                         ,"29"+                         ,"29"+                         ,"Done"+                         ]+  assertEqual "Corountine: Even more dynamic example"+    expected actual+  where+    c5 = runTrace $ runReader (loop =<< runC (th client)) (10::Int)+      where loop (Y x k) = trace (show (x::Int)) >> local (\_y->x+1) (k ()) >>= loop+            loop Done    = trace "Done"++            -- cl, client, ay are monomorphic bindings+            client = ay >> ay >> ay+            ay     = ask >>= yieldInt++            -- There is no polymorphic recursion here+            th cl = do+              cl+              v <- ask+              (if v > (20::Int) then id else local (+(5::Int))) cl+              if v > (20::Int) then return () else local (+(10::Int)) (th cl)++case_Coroutines_c7 :: Assertion+case_Coroutines_c7 = do+  ((), actual) <- catchOutput c7+  let expected = unlines ["1010"+                         ,"1021"+                         ,"1032"+                         ,"1048"+                         ,"1064"+                         ,"1080"+                         ,"1101"+                         ,"1122"+                         ,"1143"+                         ,"1169"+                         ,"1195"+                         ,"1221"+                         ,"1252"+                         ,"1283"+                         ,"1314"+                         ,"1345"+                         ,"1376"+                         ,"1407"+                         ,"Done"+                         ]+  assertEqual "Coroutine: And even more dynamic example"+    expected actual+  where+    c7 = runTrace $+          runReader (runReader (loop =<< runC (th client)) (10::Int)) (1000::Double)+     where loop (Y x k) = trace (show (x::Int)) >>+                          local (\_y->fromIntegral (x+1)::Double) (k ()) >>= loop+           loop Done    = trace "Done"++           -- cl, client, ay are monomorphic bindings+           client = ay >> ay >> ay+           ay     = ask >>= \x -> ask >>=+                     \y -> yieldInt (x + round (y::Double))++           -- There is no polymorphic recursion here+           th cl = do+             cl+             v <- ask+             (if v > (20::Int) then id else local (+(5::Int))) cl+             if v > (20::Int) then return () else local (+(10::Int)) (th cl)++case_Coroutines_c7' :: Assertion+case_Coroutines_c7' = do+  ((), actual) <- catchOutput c7'+  let expected = unlines ["1010"+                         ,"1021"+                         ,"1032"+                         ,"1048"+                         ,"1048"+                         ,"1048"+                         ,"1069"+                         ,"1090"+                         ,"1111"+                         ,"1137"+                         ,"1137"+                         ,"1137"+                         ,"1168"+                         ,"1199"+                         ,"1230"+                         ,"1261"+                         ,"1292"+                         ,"1323"+                         ,"Done"+                         ]+  assertEqual "Coroutine: And even more dynamic example"+    expected actual+  where+    c7' = runTrace $+          runReader (runReader (loop =<< runC (th client)) (10::Int)) (1000::Double)+     where loop (Y x k) = trace (show (x::Int)) >>+                          local (\_y->fromIntegral (x+1)::Double) (k ()) >>= loop+           loop Done    = trace "Done"++           -- cl, client, ay are monomorphic bindings+           client = ay >> ay >> ay+           ay     = ask >>= \x -> ask >>=+                     \y -> yieldInt (x + round (y::Double))++           -- There is no polymorphic recursion here+           th cl = do+             cl+             v <- ask+             (if v > (20::Int) then id else local (+(5::Double))) cl+             if v > (20::Int) then return () else local (+(10::Int)) (th cl)
+ test/Control/Eff/Cut/Test.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Cut.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Choose+import Control.Eff.Cut++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Cut_tcut :: Assertion+case_Cut_tcut =+  let tcut1r = run . makeChoice $ call tcut1+      tcut2r = run . makeChoice $ call tcut2+      tcut3r = run . makeChoice $ call tcut3+      tcut4r = run . makeChoice $ call tcut4+  in+    assertEqual "Cut: tcut1" [1,2] tcut1r+    >> assertEqual "Cut: nested call: tcut2" [1,2,5] tcut2r+    >> assertEqual "Cut: nested call: tcut3" [1,2,1,2,5] tcut3r+    >> assertEqual "Cut: nested call: tcut4" [1,2,1,2,5] tcut4r+  where+    -- signature is inferred+    -- tcut1 :: (Member Choose r, Member (Exc CutFalse) r) => Eff r Int+    tcut1 = (return (1::Int) `mplus'` return 2) `mplus'`+            ((cutfalse `mplus'` return 4) `mplus'`+             return 5)+    -- Here we see nested call. It poses no problems...+    tcut2 = return (1::Int) `mplus'`+            call (return 2 `mplus'` (cutfalse `mplus'` return 3) `mplus'`+                  return 4)+            `mplus'` return 5+    tcut3 = call tcut1 `mplus'` call (tcut2 `mplus'` cutfalse)+    tcut4 = call tcut1 `mplus'`  (tcut2 `mplus'` cutfalse)
+ test/Control/Eff/Example/Test.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE FlexibleContexts, AllowAmbiguousTypes #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Example.Test (testGroups, ex2) where++import Test.HUnit hiding (State)+import Test.QuickCheck+import Test.Framework.TH+import Test.Framework.Providers.HUnit+import Test.Framework.Providers.QuickCheck2++import Control.Eff+import Control.Eff.Example+import Control.Eff.Exception+import Control.Eff.Reader.Lazy+import Control.Eff.Writer.Lazy+import Control.Eff.State.Lazy+import Utils++testGroups = [ $(testGroupGenerator) ]++-- The type is inferred+-- ex2 :: Member (Exc TooBig) r => Eff r Int -> Eff r Int+ex2 m = do+  v <- m+  if v > 5 then throwExc (TooBig v)+     else return v++case_Exception1_ex2r :: Assertion+case_Exception1_ex2r = (Right 5) @=? (run ex2r)+  where+    ex2r = runReader (runErrBig (ex2 ask)) (5::Int)++case_Exception1_ex2r1 :: Assertion+case_Exception1_ex2r1 = (Left (TooBig 7)) @=? (run ex2r1)+  where+    ex2r1 = runReader (runErrBig (ex2 ask)) (7::Int)++-- Different order of handlers (layers)+case_Exception1_ex2r2 :: Assertion+case_Exception1_ex2r2 = (Left (TooBig 7)) @=? (run ex2r2)+  where+    ex2r2 = runErrBig (runReader (ex2 ask) (7::Int))++prop_Documentation_example :: [Integer] -> Property+prop_Documentation_example l = let+  ((), total1) = run $ runState (sumAll l) 0+  ((), last1) = run $ runLastWriter $ writeAll l+  (((), last2), total2) = run $ runState (runLastWriter (writeAndAdd l)) 0+  (((), total3), last3) = run $ runLastWriter $ runState (writeAndAdd l) 0+  in+   allEqual [safeLast l, last1, last2, last3]+   .&&. allEqual [sum l, total1, total2, total3]
+ test/Control/Eff/Exception/Test.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Exception.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Exception+import Control.Eff.Writer.Strict+import Data.Monoid+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++-- The type is inferred+-- et1 :: Eff r Int+et1 = return 1 `add` return 2++case_Exception1_et1 :: Assertion+case_Exception1_et1 = 3 @=? (run et1)++-- The type is inferred+-- et2 :: Member (Exc Int) r => Eff r Int+et2 = return 1 `add` throwExc (2::Int)++-- The following won't type: unhandled exception!+-- ex2rw = run et2+{-+    Could not deduce (Data.OpenUnion.FindElem (Exc Int) '[])+      arising from a use of `et2'+-}++case_Exception1_et21 :: Assertion+case_Exception1_et21 = (Left (2::Int)) @=?+  (run et21)+  where+    -- The inferred type shows that ex21 is now pure+    -- et21 :: Eff r (Either Int Int)++    et21 = runExc et2++-- Implementing the operator <|> from Alternative:+--  a <|> b does+--   -- tries a, and if succeeds, returns its result+--   -- otherwise, tries b, and if succeeds, returns its result+--   -- otherwise, throws mappend of exceptions of a and b++-- We use SetMember in the signature rather than Member to+-- ensure that the computation throws only one type of exceptions.+-- Otherwise, this construction is not very useful.+alttry :: forall e r a. (Monoid e, SetMember Exc (Exc e) r) =>+          Eff r a -> Eff r a -> Eff r a+alttry ma mb =+  catchExc ma $ \ea ->+  catchExc mb $ \eb -> throwExc (mappend (ea::e) eb)++case_Exception1_alttry :: Assertion+case_Exception1_alttry =+  [Right 10,Right 10,Right 10,Left "bummer1bummer2"] @=?+  [+  run . runExc $+     (return 1 `add` throwExc "bummer1") `alttry`+     (return 10),+  run . runExc $+     (return 10) `alttry`+     (return 1 `add` throwExc "bummer2"),+  run . runExc $+     (return 10) `alttry` return 20,+  run . runExc $+     (return 1 `add` throwExc "bummer1") `alttry`+     (return 1 `add` throwExc "bummer2")+     ]++case_Failure1_Effect :: Assertion+case_Failure1_Effect =+  let go :: Eff (Exc () ': Writer Int ': '[]) Int+         -> Int+      go = snd . run . runWriter (+) 0 . ignoreFail+      ret = go $ do+        tell (1 :: Int)+        tell (2 :: Int)+        tell (3 :: Int)+        () <- die+        tell (4 :: Int)+        return 5+   in assertEqual "Fail should stop writing" 6 ret
+ test/Control/Eff/Fresh/Test.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Fresh.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff.Fresh+import Control.Eff.Trace+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Fresh_tfresh' :: Assertion+case_Fresh_tfresh' = do+  ((), actual) <- catchOutput tfresh'+  assertEqual "Fresh: test"+    (unlines ["Fresh 0", "Fresh 1"]) actual+  where+    tfresh' = runTrace $ flip runFresh' 0 $ do+      n <- fresh+      trace $ "Fresh " ++ show n+      n <- fresh+      trace $ "Fresh " ++ show n
+ test/Control/Eff/Lift/Test.hs view
@@ -0,0 +1,220 @@+{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, NoMonomorphismRestriction #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Lift.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Exception+import Control.Eff.Lift+import Control.Eff.Reader.Strict+import Control.Eff.State.Strict+import qualified Control.Exception as Exc+import Data.Typeable+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++-- | Ensure that https://github.com/RobotGymnast/extensible-effects/issues/11 stays resolved.+case_Lift_building :: Assertion+case_Lift_building = runLift possiblyAmbiguous+  where+    possiblyAmbiguous :: (Monad m, SetMember Lift (Lift m) r) => Eff r ()+    possiblyAmbiguous = lift $ return ()++case_Lift_tl1r :: Assertion+case_Lift_tl1r = do+  ((), output) <- catchOutput tl1r+  assertEqual "Test tl1r" (showLn input) output+  where+    input = (5::Int)+    -- tl1r :: IO ()+    tl1r = runLift (runReader tl1 input)+      where+        tl1 = ask >>= \(x::Int) -> lift . print $ x++case_Lift_tMd' :: Assertion+case_Lift_tMd' = do+  actual <- catchOutput tMd'+  let expected = (output, (showLines input))+  assertEqual "Test mapMdebug using Lift" expected actual+  where+    input = [1..5]+    val = (10::Int)+    output = map (+ val) input++    tMd' = runLift $ runReader (mapMdebug' f input) val+      where f x = ask `add` return x++    -- Re-implemenation of mapMdebug using Lifting+    -- The signature is inferred+    mapMdebug'  :: (Show a, SetMember Lift (Lift IO) r) =>+                   (a -> Eff r b) -> [a] -> Eff r [b]+    mapMdebug' _f [] = return []+    mapMdebug' f (h:t) = do+      lift $ print h+      h' <- f h+      t' <- mapMdebug' f t+      return (h':t')++-- tests from <http://okmij.org/ftp/Haskell/misc.html#catch-MonadIO>+data MyException = MyException String deriving (Show, Typeable)+instance Exc.Exception MyException++exfn True = lift . Exc.throw $ (MyException "thrown")+exfn False = return True++testc m = catchDynE (m >>= return . show) (\ (MyException s) -> return s)++case_catchDynE_test1 :: Assertion+case_catchDynE_test1 = do+  ((), actual) <- catchOutput test1+  let expected = unlines [ "(\"thrown\",[\"begin\"])"+                         , "(\"True\",[\"end\",\"begin\"])"]+  assertEqual "catchDynE: test1: exception shouldn't drop Writer's state"+    expected actual+  where+    -- In CatchMonadIO, the result of tf True is ("thrown",[]) --+    -- that is, an exception will drop the Writer's state, even if that+    -- exception is caught. Here, the state is preserved!+    -- So, this is an advantage over MTL!+    test1 = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState (testc m) ([]::[String])) (x::Bool)+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x+      modify ("end":)+      return r++-- Let us use an Error effect instead+case_catchDynE_test1' :: Assertion+case_catchDynE_test1' = do+  ((), actual') <- catchOutput test1'+  let expected' = unlines [ "(Left \"thrown\",[\"begin\"])"+                         , "(Right \"True\",[\"end\",\"begin\"])"]+  assertEqual "catchDynE: test1': Error shouldn't drop Writer's state"+    expected' actual'+  where+    -- In CatchMonadIO, the result of tf True is ("thrown",[]) --+    -- that is, an exception will drop the Writer's state, even if that+    -- exception is caught. Here, the state is preserved!+    -- So, this is an advantage over MTL!+    test1' = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x+      modify ("end":)+      return r++    runErrorStr = asEStr . runExc+    asEStr :: m (Either String a) -> m (Either String a)+    asEStr = id+    exfn True = throwExc $ ("thrown")+    exfn False = return True++-- Now, the behavior of the dynamic Exception and Error effect is consistent.+-- The state is preserved. Before it wasn't.+case_catchDynE_test2 :: Assertion+case_catchDynE_test2 = do+  ((), actual) <- catchOutput test2+  let expected = unlines [ "(Left \"thrown\",[\"begin\"])"+                         , "(Right \"True\",[\"end\",\"begin\"])"]+  assertEqual "catchDynE: test2: Error shouldn't drop Writer's state"+    expected actual+  where+    test2 = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)+    runErrorStr = asEStr . runExc+    asEStr :: m (Either String a) -> m (Either String a)+    asEStr = id+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x `catchDynE` (\ (MyException s) -> throwExc s)+      modify ("end":)+      return r++-- Full recovery+case_catchDynE_test2' :: Assertion+case_catchDynE_test2' = do+  ((), actual) <- catchOutput test2'+  let expected = unlines [ "(Right \"False\",[\"end\",\"begin\"])"+                         , "(Right \"True\",[\"end\",\"begin\"])"]+  assertEqual "catchDynE: test2': Fully recover from errors"+    expected actual+  where+    test2' = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)+    runErrorStr = asEStr . runExc+    asEStr :: m (Either String a) -> m (Either String a)+    asEStr = id+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x `catchDynE` (\ (MyException _s) -> return False)+      modify ("end":)+      return r++-- Throwing within a handler+case_catchDynE_test3 :: Assertion+case_catchDynE_test3 = do+  ((), actual) <- catchOutput test3+  let expected = unlines [ "(Right \"rethrow:thrown\",[\"begin\"])"+                         , "(Right \"True\",[\"end\",\"begin\"])"]+  assertEqual "catchDynE: test3: Throwing within a handler"+    expected actual+  where+    test3 = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)+    runErrorStr = asEStr . runExc+    asEStr :: m (Either String a) -> m (Either String a)+    asEStr = id+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x `catchDynE` (\ (MyException s) ->+                                 lift . Exc.throw . MyException $+                                 ("rethrow:" ++ s))+      modify ("end":)+      return r++-- Implement the transactional behavior: when the exception is raised,+-- the state is rolled back to what it existed at the entrance to+-- the catch block.+-- This is the ``scoping behavior'' of `Handlers in action'+case_catchDynE_tran :: Assertion+case_catchDynE_tran = do+  ((), actual) <- catchOutput tran+  let expected = unlines ["(\"thrown\",[\"init\"])"+                         ,"(\"True\",[\"end\",\"begin\",\"init\"])"]+  assertEqual "catchDynE: tran: Transactional behaviour"+    expected actual+  where+    tran = do runLift (tf True) >>= print; runLift (tf False) >>= print+    tf x = runReader (runState m1 ([]::[String])) (x::Bool)+    m1 = do+      modify ("init":)+      testc (transactionState (ProxyState :: ProxyState [String]) m)+    m = do+      modify ("begin":)+      x <- ask+      r <- exfn x+      modify ("end":)+      return r+{- -- without transaction+("thrown",["begin","init"])+("True",["end","begin","init"])+-}++-- With transaction+{-+("thrown",["init"])+("True",["end","begin","init"])+-}
+ test/Control/Eff/NdetEff/Test.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.NdetEff.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.NdetEff+import Control.Eff.Writer.Strict+import Control.Monad (msum, guard, mzero, mplus)++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_NdetEff_testCA :: Assertion+case_NdetEff_testCA = [2, 4..10] @=? (run $ makeChoiceA testCA)+  where+    testCA :: (Integral a) => Eff (NdetEff ': r) a+    testCA = do+      i <- msum . fmap return $ [1..10]+      guard (i `mod` 2 == 0)+      return i++case_NdetEff_ifte :: Assertion+case_NdetEff_ifte =+  let primes = ifte_test_run+  in+    assertEqual "NdetEff: test ifte using primes"+    [2,3,5,7,11,13,17,19,23,29] primes+  where+    ifte_test = do+      n <- gen+      ifte (do+               d <- gen+               guard $ d < n && n `mod` d == 0+               -- _ <- trace ("d: " ++ show d) (return ())+           )+        (\_ -> mzero)+        (return n)+        where gen = msum . fmap return $ [2..30]++    ifte_test_run :: [Int]+    ifte_test_run = run . makeChoiceA $ ifte_test+++-- called reflect in the LogicT paper+case_NdetEff_reflect :: Assertion+case_NdetEff_reflect =+  let tsplitr10 = run $ runListWriter $ makeChoiceA tsplit+      tsplitr11 = run $ runListWriter $ makeChoiceA (msplit tsplit >>= unmsplit)+      tsplitr20 = run $ makeChoiceA $ runListWriter tsplit+      tsplitr21 = run $ makeChoiceA $ runListWriter (msplit tsplit >>= unmsplit)+  in+    assertEqual "tsplitr10" expected1 tsplitr10+    >> assertEqual "tsplitr11" expected1 tsplitr11+    >> assertEqual "tsplitr20" expected2 tsplitr20+    >> assertEqual "tsplitr21" expected21 tsplitr21+  where+    expected1 = ([1, 2],["begin", "end"])+    expected2 = [(1, ["begin"]), (2, ["end"])]+    expected21 = [(1, ["begin"]), (2, ["begin", "end"])]++    unmsplit :: Member NdetEff r => (Maybe (a, Eff r a)) -> Eff r a+    unmsplit Nothing      = mzero+    unmsplit (Just (a,m)) = return a `mplus` m++    tsplit =+      (tell "begin" >> return 1) `mplus`+      (tell "end"   >> return 2)
+ test/Control/Eff/Operational/Test.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE DataKinds, TypeOperators #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Operational.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Operational+import Control.Eff.Operational.Example as Eg+import Control.Eff.State.Lazy+import Control.Eff.Writer.Lazy++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Operational_Monad :: Assertion+case_Operational_Monad =+  let comp :: (Member (State [String]) r+               , Member (Writer String) r)+              => Eff r ()+      comp = runProgram Eg.adventPure Eg.prog+      go = snd . run . runMonoidWriter $ evalState comp ["foo", "bar"]+  in+   assertEqual+   "Evaluating Operational Monad example"+   (unlines ["getting input...",+             "ok",+             "the input is foo"]) go
+ test/Control/Eff/Reader/Lazy/Test.hs view
@@ -0,0 +1,97 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fno-warn-unused-binds #-}++module Control.Eff.Reader.Lazy.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Reader.Lazy+import Control.Monad+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++t1 = ask `add` return (1::Int)++case_Lazy1_Reader_t1 :: Assertion+case_Lazy1_Reader_t1 = let+  t1' = do v <- ask; return (v + 1 :: Int)+  t1r = runReader t1 (10::Int)+  in+    -- 'run t1' should result in type-error+    11 @=? (run t1r)++t2 = do+  v1 <- ask+  v2 <- ask+  return $ fromIntegral (v1 + (1::Int)) + (v2 + (2::Float))+++case_Lazy1_Reader_t2 :: Assertion+case_Lazy1_Reader_t2 = let+  t2r = runReader t2 (10::Int)+  t2rr = flip runReader (20::Float) . flip runReader (10::Int) $ t2+  in+    33.0 @=? (run t2rr)++-- The opposite order of layers+{- If we mess up, we get an error+t2rrr1' = run $ runReader (runReader t2 (20::Float)) (10::Float)+    No instance for (Member (Reader Int) [])+      arising from a use of `t2'+-}+case_Lazy1_Reader_t2' :: Assertion+case_Lazy1_Reader_t2' = 33.0 @=?+  (run $ runReader (runReader t2 (20::Float)) (10::Int))+++case_Lazy1_Reader_t3 :: Assertion+case_Lazy1_Reader_t3 = let+  t3 = t1 `add` local (+ (10::Int)) t1+  in+    212 @=? (run $ runReader t3 (100::Int))++-- The following example demonstrates true interleaving of Reader Int+-- and Reader Float layers+{-+t4+  :: (Member (Reader Int) r, Member (Reader Float) r) =>+     () -> Eff r Float+-}+t4 = liftM2 (+) (local (+ (10::Int)) t2)+                (local (+ (30::Float)) t2)++case_Lazy1_Reader_t4 :: Assertion+case_Lazy1_Reader_t4 = 106.0 @=?+  (run $ runReader (runReader t4 (20::Float)) (10::Int))++-- The opposite order of layers gives the same result+case_Lazy1_Reader_t4' :: Assertion+case_Lazy1_Reader_t4' = 106.0 @=?+  (run $ runReader (runReader t4 (20::Float)) (10::Int))++-- Map an effectful function+case_Lazy1_Reader_tmap :: Assertion+case_Lazy1_Reader_tmap = let+  tmap = mapM f [1..5]+  in+    ([11,12,13,14,15] :: [Int]) @=?+    (run $ runReader tmap (10::Int))+  where+    f x = ask `add` return x++case_Lazy1_Reader_runReader :: Assertion+case_Lazy1_Reader_runReader = let+  e = run $ runReader voidReader (undefined :: ())+  in+   assertNoUndefined (e :: ())+  where+    voidReader = do+        _ <- (ask :: Eff '[Reader ()] ())+        return ()
+ test/Control/Eff/Reader/Strict/Test.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Reader.Strict.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Reader.Strict+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Strict1_Reader_runReader :: Assertion+case_Strict1_Reader_runReader = let+  e = run $ runReader voidReader (undefined :: ())+  in+   assertUndefined (e :: ())+  where+    voidReader = do+        _ <- (ask :: Eff '[Reader ()] ())+        return ()
+ test/Control/Eff/State/Lazy/Test.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.State.Lazy.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.State.Lazy+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Lazy1_State_runState :: Assertion+case_Lazy1_State_runState = let+  (r, ()) = run+            $ flip runState undefined+            $ getVoid+            >> putVoid undefined+            >> putVoid ()+  in+   assertNoUndefined r+  where+    getVoid :: Eff '[State ()] ()+    getVoid = get++    putVoid :: () -> Eff '[State ()] ()+    putVoid = put
+ test/Control/Eff/State/LazyState/Test.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}++module Control.Eff.State.LazyState.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Exception+import Control.Eff.State.LazyState++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_LazierState_ex1 :: Assertion+case_LazierState_ex1 =+  let actual = run $ runStateLazy 0 lex1+  in+    assertEqual "LazyState: ex1"+    ((), 1::Int) actual+  where+    lex1 = do+      onDemand lex1+      lput (1::Int)++case_LazierState_ex3 :: Assertion+case_LazierState_ex3 =+  let (x,s) = run $ runStateLazy (undefined::[Int]) lex3+  in assertEqual "LazyState: ex3"+     ((),[1,1,1,1,1]) (x,take 5 s)+  where+    lex3 = do+      onDemand lex3+      lmodify ((1::Int):)++-- a bit more interesting+case_LazierState_ex4 =+  let (x,s) = run $ runStateLazy [] lex4+  in assertEqual "LazyState: ex4"+     expect (take 7 $ x,take 5 $ s)+  where+    expect = ([3,2,3,2,3,2,3],[3,2,3,2,3])+    lex4 :: Eff '[LazyState [Int]] [Int]+    lex4 = do+      lmodify ((0::Int):)+      onDemand lex4+      lmodify ((1::Int):)+      onDemand (onDemand lex4 :: Eff '[LazyState [Int]] [Int])+      lmodify ((2::Int):)+      lmodify ((3::Int):)+      lget+++-- Edward's example plus exceptions+case_LazierState_ex5 :: Assertion+case_LazierState_ex5 =+  let+    -- the annotations below are needed for assertEqual+    ex5Run :: Either [Int] () = fst . run . runStateLazy (undefined::[Int]) . runExc $ lex5+    ex51Run :: Either [Int] ((), [Int]) = run . runExc . runStateLazy (undefined::[Int]) $ lex5+  in+    assertEqual "LazyState ex5" (Left ones) ex5Run+    >> assertEqual "LazyState ex51" (Left ones) ex51Run+  where+    ones = take 5 $ repeat (1::Int)+    lex31 :: Member (LazyState [Int]) r => Eff r ()+    lex31 = do+      onDemand (lex31 :: Eff '[LazyState [Int]] ())+      lmodify ((1::Int):)++    lex5 = do+      lex31+      x <- lget+      throwExc ((take 5 x)::[Int])++case_LazierState_st :: Assertion+case_LazierState_st = let+  stF :: ((Int,Int,Int),Int) = run $ runStateLazy (0::Int) st+  stB0 :: ((Int,Int,Int),Int) = runStateBack0 st+  stB :: ((Int,Int,Int),Int) = runStateBack st+  in+    assertEqual "LazyState stF" ((0,1,3),4) stF+    >> assertEqual "LazyState stB0" ((1,2,4),1) stB0+    >> assertEqual "LazyState stB" ((1,2,4),1) stB+  where+    st = do+      x <- lget+      lput (1::Int)+      lput (1::Int)+      y <- lget+      lput (2::Int)+      lput (10::Int)+      lput (3::Int)+      z <- lget+      lput (4::Int)+      return (x,y,z)++case_LazierState_ones :: Assertion+case_LazierState_ones =+  let ones :: [Int] = snd $ runStateBack $ do+        s <- lget+        lput ((1::Int):s)+  in+    assertEqual "LazyState ones" [1,1,1,1,1] (take 5 ones)
+ test/Control/Eff/State/Strict/Test.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.State.Strict.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Exception+import Control.Eff.State.Strict+import Control.Eff.Reader.Strict+import Control.Eff.Writer.Strict+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Strict1_State_runState :: Assertion+case_Strict1_State_runState = let+  (r, ()) = run+            $ (flip runState) undefined+            $ getVoid+            >> putVoid undefined+            >> putVoid ()+  in+   assertUndefined r+  where+    getVoid :: Eff '[State ()] ()+    getVoid = get++    putVoid :: () -> Eff '[State ()] ()+    putVoid = put++case_Strict1_State_ts1 :: Assertion+case_Strict1_State_ts1 = (10,10) @=? (run (runState ts1 (0::Int)))+  where+    ts1 = do+      put (10 ::Int)+      x <- get+      return (x::Int)++case_Strict1_State_ts11 :: Assertion+case_Strict1_State_ts11 =+  (10,10) @=? (run (runStateR ts11 (0::Int)))+  where+    ts11 = do+      tell (10 ::Int)+      x <- ask+      return (x::Int)++case_Strict1_State_ts2 :: Assertion+case_Strict1_State_ts2 = (30::Int,20::Int) @=?+  (run (runState ts2 (0::Int)))+  where+    ts2 = do+      put (10::Int)+      x <- get+      put (20::Int)+      y <- get+      return (x+y)++case_Strict1_State_ts21 :: Assertion+case_Strict1_State_ts21 = (30::Int,20::Int) @=?+  (run (runStateR ts21 (0::Int)))+  where+    ts21 = do+      tell (10::Int)+      x <- ask+      tell (20::Int)+      y <- ask+      return (x+y)++tes1 :: (Member (State Int) r+        , Member (Exc [Char]) r) => Eff r b+tes1 = do+  incr+  throwExc "exc"+  where+    incr = get >>= put . (+ (1::Int))++case_Strict1_State_ter1 :: Assertion+case_Strict1_State_ter1 = (Left "exc" :: Either String Int,2) @=?+  (run $ runState (runExc tes1) (1::Int))++case_Strict1_State_ter2 :: Assertion+case_Strict1_State_ter2 = (Left "exc" :: Either String (Int,Int)) @=?+  (run $ runExc (runState tes1 (1::Int)))++teCatch :: Member (Exc String) r => Eff r a -> Eff r [Char]+teCatch m = catchExc (m >> return "done") (\e -> return (e::String))++case_Strict1_State_ter3 :: Assertion+case_Strict1_State_ter3 = (Right "exc" :: Either String String,2) @=?+  (run $ runState (runExc (teCatch tes1)) (1::Int))++case_Strict1_State_ter4 :: Assertion+case_Strict1_State_ter4 = (Right ("exc",2) :: Either String (String,Int)) @=?+  (run $ runExc (runState (teCatch tes1) (1::Int)))
+ test/Control/Eff/Test.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Test (testGroups) where++import Test.QuickCheck+import Control.Eff+import Control.Eff.Reader.Strict++import Test.Framework.TH+import Test.Framework.Providers.QuickCheck2++testGroups = [ $(testGroupGenerator) ]++prop_NestedEff :: Property+prop_NestedEff = forAll arbitrary (\x -> property (qu x == x))+  where+    qu :: Bool -> Bool+    qu x = run $ runReader (readerAp x) readerId++    readerAp :: Bool -> Eff '[Reader (Eff '[Reader Bool] Bool)] Bool+    readerAp x = do+      f <- ask+      return . run $ runReader f x++    readerId :: Eff '[Reader Bool] Bool+    readerId = do+      x <- ask+      return x
+ test/Control/Eff/Trace/Test.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Trace.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Reader.Strict+import Control.Eff.Trace+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Trace_tdup :: Assertion+case_Trace_tdup = do+  ((), actual) <- catchOutput tdup+  assertEqual "Trace: duplicate layers"+    (unlines ["Asked: 20", "Asked: 10"]) actual+  where+    tdup = runTrace $ runReader m (10::Int)+     where+     m = do+         runReader tr (20::Int)+         tr+     tr = do+          v <- ask+          trace $ "Asked: " ++ show (v::Int)++case_Trace_tMd :: Assertion+case_Trace_tMd = do+  actual <- catchOutput tMd+  assertEqual "Trace: higher-order effectful function"+    (map (+ val) input, unlines $ map (("mapMdebug: " ++) . show) input) actual+  where+    val = (10::Int)+    input = [1..5]+    tMd = runTrace $ runReader (mapMdebug f input) val+      where+        f x = ask `add` return x++        -- Higher-order effectful function+        -- The inferred type shows that the Trace affect is added to the effects+        -- of r+        mapMdebug:: (Show a, Member Trace r) =>+                    (a -> Eff r b) -> [a] -> Eff r [b]+        mapMdebug _f [] = return []+        mapMdebug f (h:t) = do+          trace $ "mapMdebug: " ++ show h+          h' <- f h+          t' <- mapMdebug f t+          return (h':t')
+ test/Control/Eff/Writer/Lazy/Test.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Writer.Lazy.Test (testGroups) where++import Test.HUnit hiding (State)+import Test.QuickCheck++import Control.Eff+import Control.Eff.Reader.Lazy+import Control.Eff.Writer.Lazy+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit+import Test.Framework.Providers.QuickCheck2++testGroups = [ $(testGroupGenerator) ]++addGet :: Member (Reader Int) r  => Int -> Eff r Int+addGet x = ask >>= \i -> return (i+x)++addN n = foldl (>>>) return (replicate n addGet) 0+ where f >>> g = (>>= g) . f++case_Lazy1_Writer_rdwr :: Assertion+case_Lazy1_Writer_rdwr = (10, ["begin", "end"]) @=?+  (run . (`runReader` (1::Int)) . runListWriter $ rdwr)+  where+    rdwr = do+      tell "begin"+      r <- addN 10+      tell "end"+      return r++prop_Lazy1_Writer_censor :: [Integer] -> Property+prop_Lazy1_Writer_censor l =+  property+  $ listE (mapM_ (tell . inc) l) == listE (censor inc $ mapM_ tell l)+  where+    inc :: Integer -> Integer+    inc = (+1)++    listE :: Eff '[Writer Integer] () -> [Integer]+    listE = snd . run . runListWriter++case_Lazy1_Writer_runFirstWriter :: Assertion+case_Lazy1_Writer_runFirstWriter = let+  ((), Just m) = run $ runFirstWriter $ mapM_ tell [(), undefined]+  in+   assertNoUndefined (m :: ())++case_Lazy1_Writer_runLastWriter :: Assertion+case_Lazy1_Writer_runLastWriter = let+  ((), Just m) = run $ runLastWriter $ mapM_ tell [undefined, ()]+  in+   assertNoUndefined (m :: ())
+ test/Control/Eff/Writer/Strict/Test.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}+{-# LANGUAGE TypeOperators, DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++module Control.Eff.Writer.Strict.Test (testGroups) where++import Test.HUnit hiding (State)+import Control.Eff+import Control.Eff.Writer.Strict+import Utils++import Test.Framework.TH+import Test.Framework.Providers.HUnit++testGroups = [ $(testGroupGenerator) ]++case_Strict1_Writer_runLastWriter :: Assertion+case_Strict1_Writer_runLastWriter = let+  ((), Just m) = run $ runLastWriter $ mapM_ tell [undefined, ()]+  in+   assertUndefined (m :: ())
test/Test.hs view
@@ -1,1097 +1,44 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# OPTIONS -fno-warn-missing-signatures #-}-import Control.Exception (ErrorCall, catch)-import Data.Typeable--import Test.Framework (defaultMain)-import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2-import Test.Framework.TH--import Test.HUnit hiding (State)-import Test.QuickCheck--import Control.Eff-import Data.OpenUnion-import qualified Control.Eff.Reader.Lazy as LazyR-import qualified Control.Eff.Reader.Strict as StrictR-import qualified Control.Eff.Writer.Lazy as LazyW-import qualified Control.Eff.Writer.Strict as StrictW-import qualified Control.Eff.State.Strict as StrictS-import qualified Control.Eff.State.Lazy as LazyS-import qualified Control.Eff.State.LazyState as LazierS-import Control.Eff.Exception-import Control.Eff.Choose as Choose-import Control.Eff.NdetEff-import Control.Monad (liftM2, msum, guard, mzero, mplus)-import Data.Monoid--import Control.Eff.Example as Eg-import Control.Eff.Fresh-import Control.Eff.Lift-import Control.Eff.Operational as Op-import Control.Eff.Operational.Example as Op.Eg-import Control.Eff.Trace-import Control.Eff.Coroutine-import Control.Eff.Cut---- {{{ utils: TODO: move them out--import GHC.IO.Handle-import System.IO-import System.Directory---- | capture stdout--- [[https://stackoverflow.com/a/9664017][source]]-catchOutput :: IO a -> IO (a, String)-catchOutput f = do-  tmpd <- getTemporaryDirectory-  (tmpf, tmph) <- openTempFile tmpd "haskell_stdout"-  stdout_dup <- hDuplicate stdout-  hDuplicateTo tmph stdout-  hClose tmph-  fVal <- f-  hDuplicateTo stdout_dup stdout-  str <- readFile tmpf-  removeFile tmpf-  return (fVal, str)--showLn :: Show a => a -> String-showLn x = unlines $ [show x]--showLines :: Show a => [a] -> String-showLines xs = unlines $ map show xs--withError :: a -> ErrorCall -> a-withError a _ = a--assertUndefined :: a -> Assertion-assertUndefined a = catch (seq a $ assertFailure "") (withError $ return ())--assertNoUndefined :: a -> Assertion-assertNoUndefined a = catch (seq a $ return ()) (withError $ assertFailure "")--allEqual :: Eq a => [a] -> Bool-allEqual = all (uncurry (==)) . pairs-  where-    pairs l = zip l $ tail l--safeLast [] = Nothing-safeLast l = Just $ last l---- }}}--main :: IO ()-main = $(defaultMainGenerator)---- {{{ Documentation example--prop_Documentation_example :: [Integer] -> Property-prop_Documentation_example l = let-  ((), total1) = run $ LazyS.runState (Eg.sumAll l) 0-  ((), last1) = run $ LazyW.runLastWriter $ Eg.writeAll l-  (((), last2), total2) = run $ LazyS.runState (LazyW.runLastWriter (Eg.writeAndAdd l)) 0-  (((), total3), last3) = run $ LazyW.runLastWriter $ LazyS.runState (Eg.writeAndAdd l) 0-  in-   allEqual [safeLast l, last1, last2, last3]-   .&&. allEqual [sum l, total1, total2, total3]---- }}}---- {{{ Reader--add :: Monad m => m Int -> m Int -> m Int-add = liftM2 (+)-t1 = LazyR.ask `add` return (1::Int)--case_Lazy1_Reader_t1 :: Assertion-case_Lazy1_Reader_t1 = let-  t1' = do v <- LazyR.ask; return (v + 1 :: Int)-  t1r = LazyR.runReader t1 (10::Int)-  in-    -- 'LazyR.run t1' should result in type-error-    11 @=? (run t1r)--t2 = do-  v1 <- LazyR.ask-  v2 <- LazyR.ask-  return $ fromIntegral (v1 + (1::Int)) + (v2 + (2::Float))---case_Lazy1_Reader_t2 :: Assertion-case_Lazy1_Reader_t2 = let-  t2r = LazyR.runReader t2 (10::Int)-  t2rr = flip LazyR.runReader (20::Float) . flip LazyR.runReader (10::Int) $ t2-  in-    33.0 @=? (run t2rr)---- The opposite order of layers-{- If we mess up, we get an error-t2rrr1' = run $ runReader (runReader t2 (20::Float)) (10::Float)-    No instance for (Member (Reader Int) [])-      arising from a use of `t2'--}-case_Lazy1_Reader_t2' :: Assertion-case_Lazy1_Reader_t2' = 33.0 @=?-  (run $ LazyR.runReader (LazyR.runReader t2 (20::Float)) (10::Int))---case_Lazy1_Reader_t3 :: Assertion-case_Lazy1_Reader_t3 = let-  t3 = t1 `add` LazyR.local (+ (10::Int)) t1-  in-    212 @=? (run $ LazyR.runReader t3 (100::Int))---- The following example demonstrates true interleaving of Reader Int--- and Reader Float layers-{--t4-  :: (Member (Reader Int) r, Member (Reader Float) r) =>-     () -> Eff r Float--}-t4 = liftM2 (+) (LazyR.local (+ (10::Int)) t2)-                (LazyR.local (+ (30::Float)) t2)--case_Lazy1_Reader_t4 :: Assertion-case_Lazy1_Reader_t4 = 106.0 @=?-  (run $ LazyR.runReader (LazyR.runReader t4 (20::Float)) (10::Int))---- The opposite order of layers gives the same result-case_Lazy1_Reader_t4' :: Assertion-case_Lazy1_Reader_t4' = 106.0 @=?-  (run $ LazyR.runReader (LazyR.runReader t4 (20::Float)) (10::Int))---- Map an effectful function-case_Lazy1_Reader_tmap :: Assertion-case_Lazy1_Reader_tmap = let-  tmap = mapM f [1..5]-  in-    ([11,12,13,14,15] :: [Int]) @=?-    (run $ LazyR.runReader tmap (10::Int))-  where-    f x = LazyR.ask `add` return x---- {{{ Reader.runReader--case_Lazy1_Reader_runReader :: Assertion-case_Lazy1_Reader_runReader = let-  e = run $ LazyR.runReader voidReader (undefined :: ())-  in-   assertNoUndefined (e :: ())-  where-    voidReader = do-        _ <- (LazyR.ask :: Eff '[LazyR.Reader ()] ())-        return ()--case_Strict1_Reader_runReader :: Assertion-case_Strict1_Reader_runReader = let-  e = run $ StrictR.runReader voidReader (undefined :: ())-  in-   assertUndefined (e :: ())-  where-    voidReader = do-        _ <- (StrictR.ask :: Eff '[StrictR.Reader ()] ())-        return ()---- }}}---- }}}---- {{{ State.runState---- {{{ Lazy--case_Lazy1_State_runState :: Assertion-case_Lazy1_State_runState = let-  (r, ()) = run-            $ flip LazyS.runState undefined-            $ getVoid-            >> putVoid undefined-            >> putVoid ()-  in-   assertNoUndefined r-  where-    getVoid :: Eff '[LazyS.State ()] ()-    getVoid = LazyS.get--    putVoid :: () -> Eff '[LazyS.State ()] ()-    putVoid = LazyS.put---- }}}---- {{{ Strict1--case_Strict1_State_runState :: Assertion-case_Strict1_State_runState = let-  (r, ()) = run-            $ (flip StrictS.runState) undefined-            $ getVoid-            >> putVoid undefined-            >> putVoid ()-  in-   assertUndefined r-  where-    getVoid :: Eff '[StrictS.State ()] ()-    getVoid = StrictS.get--    putVoid :: () -> Eff '[StrictS.State ()] ()-    putVoid = StrictS.put--case_Strict1_State_ts1 :: Assertion-case_Strict1_State_ts1 = (10,10) @=? (run (StrictS.runState ts1 (0::Int)))-  where-    ts1 = do-      StrictS.put (10 ::Int)-      x <- StrictS.get-      return (x::Int)--case_Strict1_State_ts11 :: Assertion-case_Strict1_State_ts11 =-  (10,10) @=? (run (StrictS.runStateR ts11 (0::Int)))-  where-    ts11 = do-      StrictW.tell (10 ::Int)-      x <- StrictR.ask-      return (x::Int)--case_Strict1_State_ts2 :: Assertion-case_Strict1_State_ts2 = (30::Int,20::Int) @=?-  (run (StrictS.runState ts2 (0::Int)))-  where-    ts2 = do-      StrictS.put (10::Int)-      x <- StrictS.get-      StrictS.put (20::Int)-      y <- StrictS.get-      return (x+y)--case_Strict1_State_ts21 :: Assertion-case_Strict1_State_ts21 = (30::Int,20::Int) @=?-  (run (StrictS.runStateR ts21 (0::Int)))-  where-    ts21 = do-      StrictW.tell (10::Int)-      x <- StrictR.ask-      StrictW.tell (20::Int)-      y <- StrictR.ask-      return (x+y)--tes1 :: (Member (StrictS.State Int) r-        , Member (Exc [Char]) r) => Eff r b-tes1 = do-  incr-  throwExc "exc"-  where-    incr = StrictS.get >>= StrictS.put . (+ (1::Int))--case_Strict1_State_ter1 :: Assertion-case_Strict1_State_ter1 = (Left "exc" :: Either String Int,2) @=?-  (run $ StrictS.runState (runExc tes1) (1::Int))--case_Strict1_State_ter2 :: Assertion-case_Strict1_State_ter2 = (Left "exc" :: Either String (Int,Int)) @=?-  (run $ runExc (StrictS.runState tes1 (1::Int)))--teCatch :: Member (Exc String) r => Eff r a -> Eff r [Char]-teCatch m = catchExc (m >> return "done") (\e -> return (e::String))--case_Strict1_State_ter3 :: Assertion-case_Strict1_State_ter3 = (Right "exc" :: Either String String,2) @=?-  (run $ StrictS.runState (runExc (teCatch tes1)) (1::Int))--case_Strict1_State_ter4 :: Assertion-case_Strict1_State_ter4 = (Right ("exc",2) :: Either String (String,Int)) @=?-  (run $ runExc (StrictS.runState (teCatch tes1) (1::Int)))---- }}}---- }}}---- {{{ Writer--addGet :: Member (LazyR.Reader Int) r  => Int -> Eff r Int-addGet x = LazyR.ask >>= \i -> return (i+x)--addN n = foldl (>>>) return (replicate n addGet) 0- where f >>> g = (>>= g) . f--case_Lazy1_Writer_rdwr :: Assertion-case_Lazy1_Writer_rdwr = (10, ["begin", "end"]) @=?-  (run . (`LazyR.runReader` (1::Int)) . LazyW.runListWriter $ rdwr)-  where-    rdwr = do-      LazyW.tell "begin"-      r <- addN 10-      LazyW.tell "end"-      return r---- {{{ Writer.censor--prop_Lazy1_Writer_censor :: [Integer] -> Property-prop_Lazy1_Writer_censor l =-  property-  $ listE (mapM_ (LazyW.tell . inc) l) == listE (LazyW.censor inc $ mapM_ LazyW.tell l)-  where-    inc :: Integer -> Integer-    inc = (+1)--    listE :: Eff '[LazyW.Writer Integer] () -> [Integer]-    listE = snd . run . LazyW.runListWriter---- }}}---- {{{ Writer.runFirstWriter--case_Lazy1_Writer_runFirstWriter :: Assertion-case_Lazy1_Writer_runFirstWriter = let-  ((), Just m) = run $ LazyW.runFirstWriter $ mapM_ LazyW.tell [(), undefined]-  in-   assertNoUndefined (m :: ())---- }}}---- {{{ Writer.runLastWriter--case_Lazy1_Writer_runLastWriter :: Assertion-case_Lazy1_Writer_runLastWriter = let-  ((), Just m) = run $ LazyW.runLastWriter $ mapM_ LazyW.tell [undefined, ()]-  in-   assertNoUndefined (m :: ())--case_Strict1_Writer_runLastWriter :: Assertion-case_Strict1_Writer_runLastWriter = let-  ((), Just m) = run $ StrictW.runLastWriter $ mapM_ StrictW.tell [undefined, ()]-  in-   assertUndefined (m :: ())---- }}}---- }}}---- {{{ Exception---- The type is inferred--- et1 :: Eff r Int-et1 = return 1 `add` return 2--case_Exception1_et1 :: Assertion-case_Exception1_et1 = 3 @=? (run et1)---- The type is inferred--- et2 :: Member (Exc Int) r => Eff r Int-et2 = return 1 `add` throwExc (2::Int)---- The following won't type: unhandled exception!--- ex2rw = run et2-{--    Could not deduce (Data.OpenUnion51.FindElem (Exc Int) '[])-      arising from a use of `et2'--}--case_Exception1_et21 :: Assertion-case_Exception1_et21 = (Left (2::Int)) @=?-  (run et21)-  where-    -- The inferred type shows that ex21 is now pure-    -- et21 :: Eff r (Either Int Int)--    et21 = runExc et2---- {{{ TooBig example from paper---- The example from the paper-newtype TooBig = TooBig Int deriving (Eq, Show)--- The type is inferred-ex2 :: Member (Exc TooBig) r => Eff r Int -> Eff r Int-ex2 m = do-  v <- m-  if v > 5 then throwExc (TooBig v)-     else return v---- specialization to tell the type of the exception-runErrBig :: Eff (Exc TooBig ': r) a -> Eff r (Either TooBig a)-runErrBig = runExc--case_Exception1_ex2r :: Assertion-case_Exception1_ex2r = (Right 5) @=? (run ex2r)-  where-    ex2r = LazyR.runReader (runErrBig (ex2 LazyR.ask)) (5::Int)--case_Exception1_ex2r1 :: Assertion-case_Exception1_ex2r1 = (Left (TooBig 7)) @=? (run ex2r1)-  where-    ex2r1 = LazyR.runReader (runErrBig (ex2 LazyR.ask)) (7::Int)---- Different order of handlers (layers)-case_Exception1_ex2r2 :: Assertion-case_Exception1_ex2r2 = (Left (TooBig 7)) @=? (run ex2r2)-  where-    ex2r2 = runErrBig (LazyR.runReader (ex2 LazyR.ask) (7::Int))---- }}}---- {{{ Alternative---- Implementing the operator <|> from Alternative:---  a <|> b does---   -- tries a, and if succeeds, returns its result---   -- otherwise, tries b, and if succeeds, returns its result---   -- otherwise, throws mappend of exceptions of a and b---- We use SetMember in the signature rather than Member to--- ensure that the computation throws only one type of exceptions.--- Otherwise, this construction is not very useful.-alttry :: forall e r a. (Monoid e, SetMember Exc (Exc e) r) =>-          Eff r a -> Eff r a -> Eff r a-alttry ma mb =-  catchExc ma $ \ea ->-  catchExc mb $ \eb -> throwExc (mappend (ea::e) eb)--case_Exception1_alttry :: Assertion-case_Exception1_alttry =-  [Right 10,Right 10,Right 10,Left "bummer1bummer2"] @=?-  [-  run . runExc $-     (return 1 `add` throwExc "bummer1") `alttry`-     (return 10),-  run . runExc $-     (return 10) `alttry`-     (return 1 `add` throwExc "bummer2"),-  run . runExc $-     (return 10) `alttry` return 20,-  run . runExc $-     (return 1 `add` throwExc "bummer1") `alttry`-     (return 1 `add` throwExc "bummer2")-     ]---- }}}---- {{{ Eff Failure--case_Failure1_Effect :: Assertion-case_Failure1_Effect =-  let go :: Eff (Exc () ': StrictW.Writer Int ': '[]) Int-         -> Int-      go = snd . run . StrictW.runWriter (+) 0 . ignoreFail-      ret = go $ do-        StrictW.tell (1 :: Int)-        StrictW.tell (2 :: Int)-        StrictW.tell (3 :: Int)-        () <- die-        StrictW.tell (4 :: Int)-        return 5-   in assertEqual "Fail should stop writing" 6 ret---- }}}---- }}}---- {{{ Choose--case_Choose1_exc11 :: Assertion-case_Choose1_exc11 = [2,3] @=? (run exc11)-  where-    exc11 = Choose.makeChoice exc1-    exc1 = return 1 `add` Choose.choose [1,2]--case_Choose_ex2 :: Assertion-case_Choose_ex2 =-  let ex2_1 = run . makeChoice . runErrBig $ ex2 (Choose.choose [5,7,1])-      ex2_2 = run . runErrBig . makeChoice $ ex2 (Choose.choose [5,7,1])-  in-    assertEqual "Choose: Combining exceptions and non-determinism: ex2_1"-    expected1 ex2_1-    >> assertEqual "Choose: Combining exceptions and non-determinism: ex2_2"-    expected2 ex2_2-  where-    expected1 = [Right 5,Left (TooBig 7),Right 1]-    expected2 = Left (TooBig 7)--case_Choose_exRec :: Assertion-case_Choose_exRec =-  let exRec_1 = run . runErrBig . makeChoice $ exRec (ex2 (Choose.choose [5,7,1]))-      exRec_2 = run . makeChoice . runErrBig $ exRec (ex2 (Choose.choose [5,7,1]))-      exRec_3 = run . runErrBig . makeChoice $ exRec (ex2 (Choose.choose [5,7,11,1]))-  in-    assertEqual "Choose: error recovery: exRec_1" expected1 exRec_1-    >> assertEqual "Choose: error recovery: exRec_2" expected2 exRec_2-    >> assertEqual "Choose: error recovery: exRec_1" expected3 exRec_3-  where-    expected1 = Right [5,7,1]-    expected2 = [Right 5,Right 7,Right 1]-    expected3 = Left (TooBig 11)-    -- Errror recovery part-    -- The code is the same as in transf1.hs. The inferred signatures differ-    -- Was: exRec :: MonadError TooBig m => m Int -> m Int-    -- exRec :: Member (Exc TooBig) r => Eff r Int -> Eff r Int-    exRec m = catchExc m handler-      where handler (TooBig n) | n <= 7 = return n-            handler e = throwExc e---- }}}---- {{{ NdetEff--case_NdetEff_testCA :: Assertion-case_NdetEff_testCA = [2, 4..10] @=? (run $ makeChoiceA testCA)-  where-    testCA :: (Integral a) => Eff (NdetEff ': r) a-    testCA = do-      i <- msum . fmap return $ [1..10]-      guard (i `mod` 2 == 0)-      return i--case_NdetEff_ifte :: Assertion-case_NdetEff_ifte =-  let primes = ifte_test_run-  in-    assertEqual "NdetEff: test ifte using primes"-    [2,3,5,7,11,13,17,19,23,29] primes-  where-    ifte_test = do-      n <- gen-      ifte (do-               d <- gen-               guard $ d < n && n `mod` d == 0-               -- _ <- trace ("d: " ++ show d) (return ())-           )-        (\_ -> mzero)-        (return n)-        where gen = msum . fmap return $ [2..30]--    ifte_test_run :: [Int]-    ifte_test_run = run . makeChoiceA $ ifte_test----- called reflect in the LogicT paper-case_NdetEff_reflect :: Assertion-case_NdetEff_reflect =-  let tsplitr10 = run $ StrictW.runListWriter $ makeChoiceA tsplit-      tsplitr11 = run $ StrictW.runListWriter $ makeChoiceA (msplit tsplit >>= unmsplit)-      tsplitr20 = run $ makeChoiceA $ StrictW.runListWriter tsplit-      tsplitr21 = run $ makeChoiceA $ StrictW.runListWriter (msplit tsplit >>= unmsplit)-  in-    assertEqual "tsplitr10" expected1 tsplitr10-    >> assertEqual "tsplitr11" expected1 tsplitr11-    >> assertEqual "tsplitr20" expected2 tsplitr20-    >> assertEqual "tsplitr21" expected21 tsplitr21-  where-    expected1 = ([1, 2],["begin", "end"])-    expected2 = [(1, ["begin"]), (2, ["end"])]-    expected21 = [(1, ["begin"]), (2, ["begin", "end"])]--    unmsplit :: Member NdetEff r => (Maybe (a, Eff r a)) -> Eff r a-    unmsplit Nothing      = mzero-    unmsplit (Just (a,m)) = return a `mplus` m--    tsplit =-      (StrictW.tell "begin" >> return 1) `mplus`-      (StrictW.tell "end"   >> return 2)---- }}}---- {{{ test Lift building---- | Ensure that https://github.com/RobotGymnast/extensible-effects/issues/11 stays resolved.-case_Lift_building :: Assertion-case_Lift_building = runLift possiblyAmbiguous-  where-    possiblyAmbiguous :: (Monad m, SetMember Lift (Lift m) r) => Eff r ()-    possiblyAmbiguous = lift $ return ()---- }}}---- {{{ Nested Eff--prop_NestedEff :: Property-prop_NestedEff = forAll arbitrary (\x -> property (qu x == x))-  where-    qu :: Bool -> Bool-    qu x = run $ StrictR.runReader (readerAp x) readerId--    readerAp :: Bool -> Eff '[StrictR.Reader (Eff '[StrictR.Reader Bool] Bool)] Bool-    readerAp x = do-      f <- StrictR.ask-      return . run $ StrictR.runReader f x--    readerId :: Eff '[StrictR.Reader Bool] Bool-    readerId = do-      x <- StrictR.ask-      return x---- }}}---- {{{ Operational Monad--case_Operational_Monad :: Assertion-case_Operational_Monad =-  let comp :: (Member (LazyS.State [String]) r-               , Member (LazyW.Writer String) r)-              => Eff r ()-      comp = Op.runProgram Op.Eg.adventPure Op.Eg.prog-      go = snd . run . LazyW.runMonoidWriter $ LazyS.evalState comp ["foo", "bar"]-  in-   assertEqual-   "Evaluating Operational Monad example"-   (unlines ["getting input...",-             "ok",-             "the input is foo"]) go---- }}}---- {{{ Yield--yieldInt :: Member (Yield Int ()) r => Int -> Eff r ()-yieldInt = yield--case_Coroutines_c1 :: Assertion-case_Coroutines_c1 = do-  ((), actual) <- catchOutput c1-  assertEqual-    "Coroutine: Simple coroutines using Eff"-    (unlines ["1", "2", "Done"]) actual-  where-    th1 :: Member (Yield Int ()) r => Eff r ()-    th1 = yieldInt 1 >> yieldInt 2--    c1 = runTrace (loop =<< runC th1)-      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop-            loop (Done)    = trace ("Done")--case_Coroutines_c2 :: Assertion-case_Coroutines_c2 = do-  ((), actual1) <- catchOutput c2-  assertEqual "Coroutine: Add dynamic variables"-    (unlines ["10", "10", "Done"]) actual1-  ((), actual2) <- catchOutput c21-  assertEqual "Coroutine: locally changing the dynamic environment for the suspension"-    (unlines ["10", "11", "Done"]) actual2-  where-    -- The code is essentially the same as that in transf.hs (only added-    -- a type specializtion on yield). The inferred signature is different though.-    -- Before it was-    --    th2 :: MonadReader Int m => CoT Int m ()-    -- Now it is more general:-    th2 :: (Member (Yield Int ()) r, Member (StrictR.Reader Int) r) => Eff r ()-    th2 = StrictR.ask >>= yieldInt >> (StrictR.ask >>= yieldInt)--    -- Code is essentially the same as in transf.hs; no liftIO though-    c2 = runTrace $ StrictR.runReader (loop =<< runC th2) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop-            loop Done    = trace "Done"--    -- locally changing the dynamic environment for the suspension-    c21 = runTrace $ StrictR.runReader (loop =<< runC th2) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> StrictR.local (+(1::Int)) (k ()) >>= loop-            loop Done    = trace "Done"--case_Coroutines_c3 :: Assertion-case_Coroutines_c3 = do-  ((), actual1) <- catchOutput c3-  assertEqual "Coroutine: two sorts of local rebinding"-    (unlines ["10", "10", "20", "20", "Done"]) actual1-  ((), actual2) <- catchOutput c31-  let expected2 = (unlines ["10", "11", "21", "21", "Done"])-  assertEqual "Coroutine: locally changing the dynamic environment for the suspension"-    expected2 actual2-  ((), actual3) <- catchOutput c4-  assertEqual "Coroutine: abstracting the client computation"-    expected2 actual3-  where-    local = StrictR.local-    ask = StrictR.ask-    runReader = StrictR.runReader--    th3 :: (Member (Yield Int ()) r, Member (StrictR.Reader Int) r) => Eff r ()-    th3 = ay >> ay >> local (+(10::Int)) (ay >> ay)-      where ay = ask >>= yieldInt--    c3 = runTrace $ runReader (loop =<< runC th3) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> k () >>= loop-            loop Done    = trace "Done"--    -- The desired result: the coroutine shares the dynamic environment with its-    -- parent; however, when the environment is locally rebound, it becomes-    -- private to coroutine.-    c31 = runTrace $ runReader (loop =<< runC th3) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> local (+(1::Int)) (k ()) >>= loop-            loop Done    = trace "Done"--    -- We now make explicit that the client computation, run by th4,-    -- is abstract. We abstract it out of th4-    c4 = runTrace $ runReader (loop =<< runC (th4 client)) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> local (+(1::Int)) (k ()) >>= loop-            loop Done    = trace "Done"--            -- cl, client, ay are monomorphic bindings-            th4 cl = cl >> local (+(10::Int)) cl-            client = ay >> ay-            ay     = ask >>= yieldInt--case_Corountines_c5 :: Assertion-case_Corountines_c5 = do-  ((), actual) <- catchOutput c5-  let expected = unlines ["10"-                         ,"11"-                         ,"12"-                         ,"18"-                         ,"18"-                         ,"18"-                         ,"29"-                         ,"29"-                         ,"29"-                         ,"29"-                         ,"29"-                         ,"29"-                         ,"Done"-                         ]-  assertEqual "Corountine: Even more dynamic example"-    expected actual-  where-    local = StrictR.local-    ask = StrictR.ask-    runReader = StrictR.runReader--    c5 = runTrace $ runReader (loop =<< runC (th client)) (10::Int)-      where loop (Y x k) = trace (show (x::Int)) >> local (\y->x+1) (k ()) >>= loop-            loop Done    = trace "Done"--            -- cl, client, ay are monomorphic bindings-            client = ay >> ay >> ay-            ay     = ask >>= yieldInt--            -- There is no polymorphic recursion here-            th cl = do-              cl-              v <- ask-              (if v > (20::Int) then id else local (+(5::Int))) cl-              if v > (20::Int) then return () else local (+(10::Int)) (th cl)--case_Coroutines_c7 :: Assertion-case_Coroutines_c7 = do-  ((), actual) <- catchOutput c7-  let expected = unlines ["1010"-                         ,"1021"-                         ,"1032"-                         ,"1048"-                         ,"1064"-                         ,"1080"-                         ,"1101"-                         ,"1122"-                         ,"1143"-                         ,"1169"-                         ,"1195"-                         ,"1221"-                         ,"1252"-                         ,"1283"-                         ,"1314"-                         ,"1345"-                         ,"1376"-                         ,"1407"-                         ,"Done"-                         ]-  assertEqual "Coroutine: And even more dynamic example"-    expected actual-  where-    local = StrictR.local-    ask = StrictR.ask-    runReader = StrictR.runReader--    c7 = runTrace $-          runReader (runReader (loop =<< runC (th client)) (10::Int)) (1000::Double)-     where loop (Y x k) = trace (show (x::Int)) >>-                          local (\y->fromIntegral (x+1)::Double) (k ()) >>= loop-           loop Done    = trace "Done"--           -- cl, client, ay are monomorphic bindings-           client = ay >> ay >> ay-           ay     = ask >>= \x -> ask >>=-                     \y -> yieldInt (x + round (y::Double))--           -- There is no polymorphic recursion here-           th cl = do-             cl-             v <- ask-             (if v > (20::Int) then id else local (+(5::Int))) cl-             if v > (20::Int) then return () else local (+(10::Int)) (th cl)--case_Coroutines_c7' :: Assertion-case_Coroutines_c7' = do-  ((), actual) <- catchOutput c7'-  let expected = unlines ["1010"-                         ,"1021"-                         ,"1032"-                         ,"1048"-                         ,"1048"-                         ,"1048"-                         ,"1069"-                         ,"1090"-                         ,"1111"-                         ,"1137"-                         ,"1137"-                         ,"1137"-                         ,"1168"-                         ,"1199"-                         ,"1230"-                         ,"1261"-                         ,"1292"-                         ,"1323"-                         ,"Done"-                         ]-  assertEqual "Coroutine: And even more dynamic example"-    expected actual-  where-    local = StrictR.local-    ask = StrictR.ask-    runReader = StrictR.runReader--    c7' = runTrace $-          runReader (runReader (loop =<< runC (th client)) (10::Int)) (1000::Double)-     where loop (Y x k) = trace (show (x::Int)) >>-                          local (\y->fromIntegral (x+1)::Double) (k ()) >>= loop-           loop Done    = trace "Done"--           -- cl, client, ay are monomorphic bindings-           client = ay >> ay >> ay-           ay     = ask >>= \x -> ask >>=-                     \y -> yieldInt (x + round (y::Double))--           -- There is no polymorphic recursion here-           th cl = do-             cl-             v <- ask-             (if v > (20::Int) then id else local (+(5::Double))) cl-             if v > (20::Int) then return () else local (+(10::Int)) (th cl)---- }}}---- {{{ Lift--case_Lift_tl1r :: Assertion-case_Lift_tl1r = do-  ((), output) <- catchOutput tl1r-  assertEqual "Test tl1r" (showLn input) output-  where-    input = (5::Int)-    -- tl1r :: IO ()-    tl1r = runLift (StrictR.runReader tl1 input)-      where-        tl1 = StrictR.ask >>= \(x::Int) -> lift . print $ x--case_Lift_tMd' :: Assertion-case_Lift_tMd' = do-  actual <- catchOutput tMd'-  let expected = (output, (showLines input))-  assertEqual "Test mapMdebug using Lift" expected actual-  where-    input = [1..5]-    val = (10::Int)-    output = map (+ val) input--    tMd' = runLift $ StrictR.runReader (mapMdebug' f input) val-      where f x = StrictR.ask `add` return x--    -- Re-implemenation of mapMdebug using Lifting-    -- The signature is inferred-    mapMdebug'  :: (Show a, SetMember Lift (Lift IO) r) =>-                   (a -> Eff r b) -> [a] -> Eff r [b]-    mapMdebug' f [] = return []-    mapMdebug' f (h:t) = do-      lift $ print h-      h' <- f h-      t' <- mapMdebug' f t-      return (h':t')---- }}}---- {{{ Trace--case_Trace_tdup :: Assertion-case_Trace_tdup = do-  ((), actual) <- catchOutput tdup-  assertEqual "Trace: duplicate layers"-    (unlines ["Asked: 20", "Asked: 10"]) actual-  where-    tdup = runTrace $ StrictR.runReader m (10::Int)-     where-     m = do-         StrictR.runReader tr (20::Int)-         tr-     tr = do-          v <- StrictR.ask-          trace $ "Asked: " ++ show (v::Int)--case_Trace_tMd :: Assertion-case_Trace_tMd = do-  actual <- catchOutput tMd-  assertEqual "Trace: higher-order effectful function"-    (map (+ val) input, unlines $ map (("mapMdebug: " ++) . show) input) actual-  where-    val = (10::Int)-    input = [1..5]-    tMd = runTrace $ StrictR.runReader (mapMdebug f input) val-      where-        f x = StrictR.ask `add` return x--        -- Higher-order effectful function-        -- The inferred type shows that the Trace affect is added to the effects-        -- of r-        mapMdebug:: (Show a, Member Trace r) =>-                    (a -> Eff r b) -> [a] -> Eff r [b]-        mapMdebug f [] = return []-        mapMdebug f (h:t) = do-          trace $ "mapMdebug: " ++ show h-          h' <- f h-          t' <- mapMdebug f t-          return (h':t')---- }}}---- {{{ Fresh--case_Fresh_tfresh' :: Assertion-case_Fresh_tfresh' = do-  ((), actual) <- catchOutput tfresh'-  assertEqual "Fresh: test"-    (unlines ["Fresh 0", "Fresh 1"]) actual-  where-    tfresh' = runTrace $ flip runFresh' 0 $ do-      n <- fresh-      trace $ "Fresh " ++ show n-      n <- fresh-      trace $ "Fresh " ++ show n---- }}}---- {{{ LazyState--case_LazierState_ex1 :: Assertion-case_LazierState_ex1 =-  let actual = run $ LazierS.runStateLazy 0 lex1-  in-    assertEqual "LazyState: ex1"-    ((), 1::Int) actual-  where-    lex1 = do-      LazierS.onDemand lex1-      LazierS.lput (1::Int)--case_LazierState_ex3 :: Assertion-case_LazierState_ex3 =-  let (x,s) = run $ LazierS.runStateLazy (undefined::[Int]) lex3-  in assertEqual "LazyState: ex3"-     ((),[1,1,1,1,1]) (x,take 5 s)-  where-    lex3 = do-      LazierS.onDemand lex3-      LazierS.lmodify ((1::Int):)---- a bit more interesting-case_LazierState_ex4 =-  let (x,s) = run $ LazierS.runStateLazy [] lex4-  in assertEqual "LazyState: ex4"-     expect (take 7 $ x,take 5 $ s)-  where-    expect = ([3,2,3,2,3,2,3],[3,2,3,2,3])-    lex4 :: Eff '[LazierS.LazyState [Int]] [Int]-    lex4 = do-      LazierS.lmodify ((0::Int):)-      LazierS.onDemand lex4-      LazierS.lmodify ((1::Int):)-      LazierS.onDemand (LazierS.onDemand lex4 :: Eff '[LazierS.LazyState [Int]] [Int])-      LazierS.lmodify ((2::Int):)-      LazierS.lmodify ((3::Int):)-      LazierS.lget----- Edward's example plus exceptions-case_LazierState_ex5 :: Assertion-case_LazierState_ex5 =-  let-    -- the annotations below are needed for assertEqual-    ex5Run :: Either [Int] () = fst . run . LazierS.runStateLazy (undefined::[Int]) . runExc $ lex5-    ex51Run :: Either [Int] ((), [Int]) = run . runExc . LazierS.runStateLazy (undefined::[Int]) $ lex5-  in-    assertEqual "LazyState ex5" (Left ones) ex5Run-    >> assertEqual "LazyState ex51" (Left ones) ex51Run-  where-    ones = take 5 $ repeat (1::Int)-    lex31 :: Member (LazierS.LazyState [Int]) r => Eff r ()-    lex31 = do-      LazierS.onDemand (lex31 :: Eff '[LazierS.LazyState [Int]] ())-      LazierS.lmodify ((1::Int):)--    lex5 = do-      lex31-      x <- LazierS.lget-      throwExc ((take 5 x)::[Int])--case_LazierState_st :: Assertion-case_LazierState_st = let-  stF :: ((Int,Int,Int),Int) = run $ LazierS.runStateLazy (0::Int) st-  stB0 :: ((Int,Int,Int),Int) = LazierS.runStateBack0 st-  stB :: ((Int,Int,Int),Int) = LazierS.runStateBack st-  in-    assertEqual "LazyState stF" ((0,1,3),4) stF-    >> assertEqual "LazyState stB0" ((1,2,4),1) stB0-    >> assertEqual "LazyState stB" ((1,2,4),1) stB-  where-    st = do-      x <- LazierS.lget-      LazierS.lput (1::Int)-      LazierS.lput (1::Int)-      y <- LazierS.lget-      LazierS.lput (2::Int)-      LazierS.lput (10::Int)-      LazierS.lput (3::Int)-      z <- LazierS.lget-      LazierS.lput (4::Int)-      return (x,y,z)--case_LazierState_ones :: Assertion-case_LazierState_ones =-  let ones :: [Int] = snd $ LazierS.runStateBack $ do-        s <- LazierS.lget-        LazierS.lput ((1::Int):s)-  in-    assertEqual "LazyState ones" [1,1,1,1,1] (take 5 ones)---- }}}---- {{{ Cut--case_Cut_tcut :: Assertion-case_Cut_tcut =-  let tcut1r = run . makeChoice $ call tcut1-      tcut2r = run . makeChoice $ call tcut2-      tcut3r = run . makeChoice $ call tcut3-      tcut4r = run . makeChoice $ call tcut4-  in-    assertEqual "Cut: tcut1" [1,2] tcut1r-    >> assertEqual "Cut: nested call: tcut2" [1,2,5] tcut2r-    >> assertEqual "Cut: nested call: tcut3" [1,2,1,2,5] tcut3r-    >> assertEqual "Cut: nested call: tcut4" [1,2,1,2,5] tcut4r-  where-    -- signature is inferred-    -- tcut1 :: (Member Choose r, Member (Exc CutFalse) r) => Eff r Int-    tcut1 = (return (1::Int) `mplus'` return 2) `mplus'`-            ((cutfalse `mplus'` return 4) `mplus'`-             return 5)-    -- Here we see nested call. It poses no problems...-    tcut2 = return (1::Int) `mplus'`-            call (return 2 `mplus'` (cutfalse `mplus'` return 3) `mplus'`-                  return 4)-            `mplus'` return 5-    tcut3 = call tcut1 `mplus'` call (tcut2 `mplus'` cutfalse)-    tcut4 = call tcut1 `mplus'`  (tcut2 `mplus'` cutfalse)---- }}}+import Test.Framework (defaultMain, Test)++import qualified Control.Eff.Test+import qualified Control.Eff.Choose.Test+import qualified Control.Eff.Coroutine.Test+import qualified Control.Eff.Cut.Test+import qualified Control.Eff.Example.Test+import qualified Control.Eff.Exception.Test+import qualified Control.Eff.Fresh.Test+import qualified Control.Eff.Lift.Test+import qualified Control.Eff.NdetEff.Test+import qualified Control.Eff.Operational.Test+import qualified Control.Eff.Reader.Lazy.Test+import qualified Control.Eff.Reader.Strict.Test+import qualified Control.Eff.State.Lazy.Test+import qualified Control.Eff.State.LazyState.Test+import qualified Control.Eff.State.Strict.Test+import qualified Control.Eff.Trace.Test+import qualified Control.Eff.Writer.Lazy.Test+import qualified Control.Eff.Writer.Strict.Test++main :: IO ()+main = defaultMain testGroups++testGroups :: [Test]+testGroups = []+             ++ Control.Eff.Test.testGroups+             ++ Control.Eff.Choose.Test.testGroups+             ++ Control.Eff.Coroutine.Test.testGroups+             ++ Control.Eff.Cut.Test.testGroups+             ++ Control.Eff.Example.Test.testGroups+             ++ Control.Eff.Exception.Test.testGroups+             ++ Control.Eff.Fresh.Test.testGroups+             ++ Control.Eff.Lift.Test.testGroups+             ++ Control.Eff.NdetEff.Test.testGroups+             ++ Control.Eff.Operational.Test.testGroups+             ++ Control.Eff.Reader.Lazy.Test.testGroups+             ++ Control.Eff.Reader.Strict.Test.testGroups+             ++ Control.Eff.State.Lazy.Test.testGroups+             ++ Control.Eff.State.LazyState.Test.testGroups+             ++ Control.Eff.State.Strict.Test.testGroups+             ++ Control.Eff.Trace.Test.testGroups+             ++ Control.Eff.Writer.Lazy.Test.testGroups+             ++ Control.Eff.Writer.Strict.Test.testGroups
+ test/Utils.hs view
@@ -0,0 +1,54 @@+{-# OPTIONS_GHC -Werror #-}++module Utils where++import Control.Exception (ErrorCall, catch)+import Control.Monad++import GHC.IO.Handle+import System.IO+import System.Directory++import Test.HUnit hiding (State)++-- | capture stdout+-- [[https://stackoverflow.com/a/9664017][source]]+catchOutput :: IO a -> IO (a, String)+catchOutput f = do+  tmpd <- getTemporaryDirectory+  (tmpf, tmph) <- openTempFile tmpd "haskell_stdout"+  stdout_dup <- hDuplicate stdout+  hDuplicateTo tmph stdout+  hClose tmph+  fVal <- f+  hDuplicateTo stdout_dup stdout+  str <- readFile tmpf+  removeFile tmpf+  return (fVal, str)++showLn :: Show a => a -> String+showLn x = unlines $ [show x]++showLines :: Show a => [a] -> String+showLines xs = unlines $ map show xs++withError :: a -> ErrorCall -> a+withError a _ = a++assertUndefined :: a -> Assertion+assertUndefined a = catch (seq a $ assertFailure "") (withError $ return ())++assertNoUndefined :: a -> Assertion+assertNoUndefined a = catch (seq a $ return ()) (withError $ assertFailure "")++allEqual :: Eq a => [a] -> Bool+allEqual = all (uncurry (==)) . pairs+  where+    pairs l = zip l $ tail l++safeLast :: [a] -> Maybe a+safeLast [] = Nothing+safeLast l = Just $ last l++add :: Monad m => m Int -> m Int -> m Int+add = liftM2 (+)