packages feed

effects 0.2 → 0.2.1

raw patch · 15 files changed

+157/−10 lines, 15 filesbinary-added

Files

+ ._LICENSE view

binary file changed (absent → 185 bytes)

+ ._README.md view

binary file changed (absent → 187 bytes)

+ ._effects.cabal view

binary file changed (absent → 186 bytes)

+ ._examples.hs view

binary file changed (absent → 187 bytes)

+ README.md view
@@ -0,0 +1,28 @@+Control.Effects+===============++Control.Effects is a Haskell library for programming with effects, like in the the [Eff language][Eff] by Andrej Bauer and Matija Pretnar. Effects can be used instead of monad transformers, they are designed to be easier to use and to define.++Installation+------------++    cabal install effects++Using effects+-------------++Here's an example how to use the state effect from `Control.Effects.State`.++    example :: (Int, Int)+    example = run $ do+      with (ref 5) $ \x -> do+        with (ref 10) $ \y -> do+          x =: (+) <$> get x <*> get y+          y =: (+) <$> get x <*> get y+          (,) <$> get x <*> get y++Every instance of an effect is given a name (`x` and `y` in this example), which makes is possible to easily mix several instances of the same effect.++For more examples see [examples.hs](https://github.com/sjoerdvisscher/effects/blob/master/examples.hs).++[Eff]: http://math.andrej.com/category/programming/eff/?category_name=programming/eff
effects.cabal view
@@ -1,5 +1,5 @@ name:                effects-version:             0.2+version:             0.2.1 synopsis:            Computational Effects  description:         Control.Effects is a library for programming with effects, like in the the Eff language by 
+ examples.hs view
@@ -0,0 +1,109 @@+module Main where++import Control.Effects+import Control.Effects.Cont+import Control.Effects.Either+import Control.Effects.Error+import Control.Effects.State+import Control.Effects.Writer+import Control.Effects.NonDet++import qualified Data.Set as Set+import Data.Monoid+import Control.Applicative+++testIO :: IO ()+testIO = runBase $ do+  base $ putStrLn "What's your name?"+  name <- base getLine+  base $ putStrLn $ "Hello, " ++ name++testRefIO :: IO ()+testRefIO = runBase $ do+  with (ref 5) $ \x -> do+    val <- get x+    base $ print val++testRef :: (Int, Int)+testRef = run $ do+  with (ref 5) $ \x -> do+    with (ref 10) $ \y -> do+      x =: (+) <$> get x <*> get y+      y =: (+) <$> get x <*> get y+      (,) <$> get x <*> get y+      ++testWriter :: (String, (String, Int))+testWriter = run $ do+  with writer $ \w1 -> do+    with writer $ \w2 -> do+      tell w1 "123"+      tell w2 "abc"+      tell w1 "456"+      tell w2 "def"+      return 1+++testSet :: Set.Set Int+testSet = run $+  with set $ \s -> do+    x <- choose s [1, 2]+    y <- choose s [1, 2]+    z <- choose s [1, 2]+    return $ x * x - y * z * x + z * z * z - y * y * x++testAccumulate :: Bool+testAccumulate = run $+  with (accumulate Any) $ \s -> do+    x <- choose s [1, 2]+    y <- choose s [1, 2]+    z <- choose s [1, 2]+    return $ x * x - y * z * x + z * z * z - y * y * x == 0+++testDfs :: [Int] -> [(Int, Int, Int)]+testDfs = run . with (dfs return) . triples++testBfs :: [Int] -> [(Int, Int, Int)]+testBfs = run . with (bfs return) . triples++triples :: (Num a, Monoid e, AutoLift e m n) => [a] -> Effect e m -> n (a, a, a)+triples range s = do+  x <- choose s range+  y <- choose s range+  z <- choose s range+  if x*x + y*y == z*z then return (x,y,z) else choose s []+++testError :: IO ()+testError = runBase $ do+  with (catchError (\e -> base $ putStrLn ("Error: " ++ e))) $ \c -> do+    base $ putStrLn "before"+    throwError c "123"+    base $ putStrLn "after"+  ++testEither :: IO ()+testEither = runBase $ do+  with (catchEither (\e -> base $ putStrLn ("Error: " ++ e))) $ \c -> do+    base $ putStrLn "before"+    throwEither c "123"+    base $ putStrLn "after"+++testReset1 :: Int+testReset1 = run $ do+  with reset $ \r -> do+    x <- shift r (\k -> k (k (k (return 7))))+    return $ x * 2 + 1++testReset2 :: IO ()+testReset2 = runBase $ do+  r <- with reset $ \promptA -> do+    base $ putStrLn "Batman"+    with reset $ \promptB -> do+      shift promptB $ \k -> k (k (shift promptA $ \l -> l (l (return ()))))+      base $ putStrLn "Robin"+    base $ putStrLn "Cat woman"+  base $ print r
+ src/Control/._Effects.hs view

binary file changed (absent → 187 bytes)

src/Control/Effects.hs view
@@ -15,9 +15,9 @@   , base   -- * Effects machinery   -- $macdoc-  , Layer-  , Base-  , Pure+  , Layer(..)+  , Base(..)+  , Pure(..)   , Effect   , AutoLift   , AutoLiftBase@@ -25,9 +25,11 @@ ) where  import Control.Applicative+import Control.Monad+import Data.Monoid  -- $rundoc--- Here's an example how to use the state effect from 'Control.Effects.State'.+-- Here's an example how to use the state effect from 'Control.Effects.State': -- -- > example :: Int -- > example = run $ do@@ -47,7 +49,7 @@   -- $defdoc--- Here's and example how to define the state effect from 'Control.Effects.Writer'.+-- Here's and example how to define the state effect from 'Control.Effects.Writer': -- -- > writer :: (Monad m, Monoid w) => Handler (w, a) (w, a) m a -- > writer = Handler@@ -63,7 +65,7 @@ -- | A @Handler e r m a@ is a handler of effects with type @e@.  --   The @ret@ field provides a function to lift pure values into the effect. --   The @fin@ field provides a function to extract a final value of type @r@ from the effect.---   The parameter @m@ should narmally be left polymorphic, it's the monad that handles the other effects.+--   The parameter @m@ should normally be left polymorphic, it's the monad that handles the other effects. data Handler e r m a = Handler   { ret :: a -> m e   , fin :: e -> m r@@ -76,7 +78,7 @@   -- $basedoc--- The effects are layered on top of a base monad. Here's an example how to use `IO` as a base monad.+-- The effects are layered on top of a base monad. Here's an example how to use `IO` as a base monad: --  -- > exampleIO :: IO () -- > exampleIO = runBase $ do@@ -105,16 +107,24 @@ --   (It is the continuation monad transformer with a friendlier name.) newtype Layer e m a = Layer { runLayer :: (a -> m e) -> m e } -instance Functor (Layer r m) where+instance Functor (Layer e m) where   fmap f m = Layer $ \k -> runLayer m (k . f) -instance Applicative (Layer r m) where+instance Applicative (Layer e m) where   pure a   = Layer $ \k -> k a   m <*> v  = Layer $ \k -> runLayer m (\f -> runLayer v (k . f)) +instance (Monoid e, Applicative m) => Alternative (Layer e m) where+  empty = Layer $ \_ -> pure mempty+  l <|> r = Layer $ \k -> mappend <$> runLayer l k <*> runLayer r k+ instance Monad (Layer e m) where   return a = Layer $ \k -> k a   m >>= f  = Layer $ \k -> runLayer m (\a -> runLayer (f a) k)++instance (Monoid e, Applicative m) => MonadPlus (Layer e m) where+  mzero = empty+  mplus = (<|>)   -- | @Pure@ is the identity monad and is used when no other base monad is needed.
+ src/Control/Effects/._Cont.hs view

binary file changed (absent → 186 bytes)

+ src/Control/Effects/._Either.hs view

binary file changed (absent → 186 bytes)

+ src/Control/Effects/._Error.hs view

binary file changed (absent → 186 bytes)

+ src/Control/Effects/._NonDet.hs view

binary file changed (absent → 186 bytes)

+ src/Control/Effects/._State.hs view

binary file changed (absent → 186 bytes)

+ src/Control/Effects/._Writer.hs view

binary file changed (absent → 186 bytes)