packages feed

objective 1.1.1 → 1.1.2

raw patch · 10 files changed

+801/−796 lines, 10 filesdep −eitherdep ~freesetup-changed

Dependencies removed: either

Dependency ranges changed: free

Files

.travis.yml view
@@ -1,56 +1,56 @@-# NB: don't set `language: haskell` here
-
-# See also https://github.com/hvr/multi-ghc-travis for more information
-
-# The following lines enable several GHC versions and/or HP versions
-# to be tested; often it's enough to test only against the last
-# release of a major GHC version. Setting HPVER implictly sets
-# GHCVER. Omit lines with versions you don't need/want testing for.
-env:
- - CABALVER=1.18 GHCVER=7.6.3
- - CABALVER=1.18 GHCVER=7.8.4
- - CABALVER=1.22 GHCVER=7.10.1
-
-# Note: the distinction between `before_install` and `install` is not
-#       important.
-before_install:
- - travis_retry sudo add-apt-repository -y ppa:hvr/ghc
- - travis_retry sudo apt-get update
- - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER
- - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
-
-install:
- - cabal --version
- - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- - travis_retry cabal update
- - cabal install --only-dependencies --enable-tests --enable-benchmarks
-
-# Here starts the actual work to be performed for the package under
-# test; any command which exits with a non-zero exit code causes the
-# build to fail.
-script:
- - if [ -f configure.ac ]; then autoreconf -i; fi
- # -v2 provides useful information for debugging
- - cabal configure --enable-tests --enable-benchmarks -v2
-
- # this builds all libraries and executables
- # (including tests/benchmarks)
- - cabal build
-
- - cabal test
- - cabal check
-
- # tests that a source-distribution can be generated
- - cabal sdist
-
- # check that the generated source-distribution can be built & installed
- - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ;
-   cd dist/;
-   if [ -f "$SRC_TGZ" ]; then
-      cabal install --force-reinstalls "$SRC_TGZ";
-   else
-      echo "expected '$SRC_TGZ' not found";
-      exit 1;
-   fi
-
-# EOF
+# NB: don't set `language: haskell` here++# See also https://github.com/hvr/multi-ghc-travis for more information++# The following lines enable several GHC versions and/or HP versions+# to be tested; often it's enough to test only against the last+# release of a major GHC version. Setting HPVER implictly sets+# GHCVER. Omit lines with versions you don't need/want testing for.+env:+ - CABALVER=1.18 GHCVER=7.6.3+ - CABALVER=1.18 GHCVER=7.8.4+ - CABALVER=1.22 GHCVER=7.10.1++# Note: the distinction between `before_install` and `install` is not+#       important.+before_install:+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc+ - travis_retry sudo apt-get update+ - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH++install:+ - cabal --version+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"+ - travis_retry cabal update+ - cabal install --only-dependencies --enable-tests --enable-benchmarks++# Here starts the actual work to be performed for the package under+# test; any command which exits with a non-zero exit code causes the+# build to fail.+script:+ - if [ -f configure.ac ]; then autoreconf -i; fi+ # -v2 provides useful information for debugging+ - cabal configure --enable-tests --enable-benchmarks -v2++ # this builds all libraries and executables+ # (including tests/benchmarks)+ - cabal build++ - cabal test+ - cabal check++ # tests that a source-distribution can be generated+ - cabal sdist++ # check that the generated source-distribution can be built & installed+ - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ;+   cd dist/;+   if [ -f "$SRC_TGZ" ]; then+      cabal install --force-reinstalls "$SRC_TGZ";+   else+      echo "expected '$SRC_TGZ' not found";+      exit 1;+   fi++# EOF
CHANGELOG.md view
@@ -1,114 +1,119 @@-1.1
-----
-* Removed `HProfunctor`, `(..-)`, `invokeOnSTM`, `newSTM`, `snapshot`
-* Added `(?-)`
-
-1.0.5
-----
-* Added `filterO` and `filteredO`
-* Renamed `announcesOf` to `invokesOf`
-* Added `invokes`
-* Added `(@!=)`
-* Shaved unnecessary `Monoid r` off in `apprisesOf`
-
-1.0.4
-----
-* Simplified `Instance`
-* Added `snapshot`
-* Added `cascade`, `cascadeObject`
-* Added `announcesOf`
-* Added `(@||@)`
-* Safe Haskell
-
-1.0.3
-----
-* Added `apprisesOf`
-* Added `(@~)`
-
-1.0.2
-----
-* Made `(.-)` exception-safe
-
-1.0.1
-----
-* Switched to use TMVar for instances
-* Added atomic operations
-* Add `apprises`
-* Re-added `accept`
-* Added `(>~~>)`
-* Added `accumulator`
-
-1.0
-----
-* No longer support `extensible`, `elevator`, and `minioperational`
-* Removed `Data.Functor.PushPull`
-* Removed `Control.Object.Process`
-* Removed `Control.Object.Stream`
-* Removed `Control.Monad.Objective`
-* Added `apprise`
-* Generalized `(^>>@)` and `(@>>^)` so that they also work on instances
-
-0.6.5
-----
-* Supported `elevator >= 0.2`.
-
-0.6.3.1
-----
-* Reverted the fixity.
-
-0.6.3
-----
-* Added `Variable`, an alias for `variable` objects.
-* Added `Mortal`.
-* Increased fixity of invocation operators to 5.
-* Added stream connection operators.
-* Added `transit` and `animate`.
-
-0.6.2
-----
-* Added `announce`, `announceMaybe` and `announceMaybeT` which invoke a method for every objects in a container.
-* Added `(@**@)` and `(@||@)`.
-* Renamed `(.>>.)` to `(@>>@)`, `.|>.` to `(@|>@)` for consistency.
-* Added `filterPush`, `bipush`, `bipull`.
-* Added `iterObject`, `iterTObject`, `iterative`, `iterativeT` for free monads.
-* Renamed `runSequential` to `(@!)`.
-* Added combinators for `ReifiedProgramT`: `(@!!)` and `sequentialT`.
-* Changed the semantics of `variable` to accept `StateT`.
-* Added `flyweight'` that relies on HashMap.
-* Added `MonadObjective` constraint
-
-0.6.1
------
-* Fixed the wrong constraints of `request`
-
-0.6
------
-* `PushPull` has more `Floors`
-* Added `Applicative` instance for `Request`
-* Reformed around Control.Monad.Objective
-  * Instance f g m ==> Inst m f g
-  * `invoke` takes two transformations for lifting
-  * Added lifted versions of `new`: `newIO` and `newST`
-
-0.5.2
------
-* Added Process
-* Added `runSequential`, `sequential` for operational monad
-* Added `flyweight`
-
-0.5.1
------
-* Added PushPull functor
-* Removed `sequential`
-
-0.5
------
-* Lift has gone
-* Use elevator instead of Lift
-* Moved Request to a separate module
-
-0.4
------
-* Added Request functor along with Lift
-* Supported "extensible" objects using open unions
-* AccessT is now obsolete
+1.1.2+----++* Removed `either` dependency++1.1+----+* Removed `HProfunctor`, `(..-)`, `invokeOnSTM`, `newSTM`, `snapshot`+* Added `(?-)`++1.0.5+----+* Added `filterO` and `filteredO`+* Renamed `announcesOf` to `invokesOf`+* Added `invokes`+* Added `(@!=)`+* Shaved unnecessary `Monoid r` off in `apprisesOf`++1.0.4+----+* Simplified `Instance`+* Added `snapshot`+* Added `cascade`, `cascadeObject`+* Added `announcesOf`+* Added `(@||@)`+* Safe Haskell++1.0.3+----+* Added `apprisesOf`+* Added `(@~)`++1.0.2+----+* Made `(.-)` exception-safe++1.0.1+----+* Switched to use TMVar for instances+* Added atomic operations+* Add `apprises`+* Re-added `accept`+* Added `(>~~>)`+* Added `accumulator`++1.0+----+* No longer support `extensible`, `elevator`, and `minioperational`+* Removed `Data.Functor.PushPull`+* Removed `Control.Object.Process`+* Removed `Control.Object.Stream`+* Removed `Control.Monad.Objective`+* Added `apprise`+* Generalized `(^>>@)` and `(@>>^)` so that they also work on instances++0.6.5+----+* Supported `elevator >= 0.2`.++0.6.3.1+----+* Reverted the fixity.++0.6.3+----+* Added `Variable`, an alias for `variable` objects.+* Added `Mortal`.+* Increased fixity of invocation operators to 5.+* Added stream connection operators.+* Added `transit` and `animate`.++0.6.2+----+* Added `announce`, `announceMaybe` and `announceMaybeT` which invoke a method for every objects in a container.+* Added `(@**@)` and `(@||@)`.+* Renamed `(.>>.)` to `(@>>@)`, `.|>.` to `(@|>@)` for consistency.+* Added `filterPush`, `bipush`, `bipull`.+* Added `iterObject`, `iterTObject`, `iterative`, `iterativeT` for free monads.+* Renamed `runSequential` to `(@!)`.+* Added combinators for `ReifiedProgramT`: `(@!!)` and `sequentialT`.+* Changed the semantics of `variable` to accept `StateT`.+* Added `flyweight'` that relies on HashMap.+* Added `MonadObjective` constraint++0.6.1+-----+* Fixed the wrong constraints of `request`++0.6+-----+* `PushPull` has more `Floors`+* Added `Applicative` instance for `Request`+* Reformed around Control.Monad.Objective+  * Instance f g m ==> Inst m f g+  * `invoke` takes two transformations for lifting+  * Added lifted versions of `new`: `newIO` and `newST`++0.5.2+-----+* Added Process+* Added `runSequential`, `sequential` for operational monad+* Added `flyweight`++0.5.1+-----+* Added PushPull functor+* Removed `sequential`++0.5+-----+* Lift has gone+* Use elevator instead of Lift+* Moved Request to a separate module++0.4+-----+* Added Request functor along with Lift+* Supported "extensible" objects using open unions+* AccessT is now obsolete
LICENSE view
@@ -1,30 +1,30 @@-Copyright (c) 2014, Fumiaki Kinoshita
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of Fumiaki Kinoshita nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c) 2014, Fumiaki Kinoshita++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Fumiaki Kinoshita nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple
-main = defaultMain
+import Distribution.Simple+main = defaultMain
objective.cabal view
@@ -1,48 +1,47 @@-name:                objective
-version:             1.1.1
-synopsis:            Composable objects
-description:         Composable objects
-homepage:            https://github.com/fumieval/objective
-bug-reports:         http://github.com/fumieval/objective/issues
-license:             BSD3
-license-file:        LICENSE
-author:              Fumiaki Kinoshita
-maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>
-copyright:           Copyright (c) 2014 Fumiaki Kinoshita
-category:            Control
-build-type:          Simple
-extra-source-files:
-  CHANGELOG.md
-  .travis.yml
-cabal-version:       >=1.10
-
-source-repository head
-  type: git
-  location: https://github.com/fumieval/objective.git
-
-library
-  exposed-modules:
-    Control.Object
-      , Control.Object.Object
-      , Control.Object.Instance
-      , Control.Object.Mortal
-      , Data.Functor.Request
-  other-extensions:    MultiParamTypeClasses, KindSignatures, TypeFamilies
-  build-depends:       base >=4.6 && <5
-    , either >= 4.3 && <4.5
-    , exceptions >= 0.8
-    , containers >= 0.5.0.0 && <0.6
-    , unordered-containers >= 0.2.0.0 && <0.3
-    , transformers >= 0.3 && <0.6
-    , transformers-compat
-    , free >= 4 && <5
-    , hashable
-    , mtl
-    , profunctors
-    , void
-    , witherable >= 0.1.3
-    , monad-skeleton >= 0.1.1 && <0.3
-    , template-haskell
-  ghc-options: -Wall
-  hs-source-dirs:      src
-  default-language:    Haskell2010
+name:                objective+version:             1.1.2+synopsis:            Composable objects+description:         Composable objects+homepage:            https://github.com/fumieval/objective+bug-reports:         http://github.com/fumieval/objective/issues+license:             BSD3+license-file:        LICENSE+author:              Fumiaki Kinoshita+maintainer:          Fumiaki Kinoshita <fumiexcel@gmail.com>+copyright:           Copyright (c) 2014 Fumiaki Kinoshita+category:            Control+build-type:          Simple+extra-source-files:+  CHANGELOG.md+  .travis.yml+cabal-version:       >=1.10++source-repository head+  type: git+  location: https://github.com/fumieval/objective.git++library+  exposed-modules:+    Control.Object+      , Control.Object.Object+      , Control.Object.Instance+      , Control.Object.Mortal+      , Data.Functor.Request+  other-extensions:    MultiParamTypeClasses, KindSignatures, TypeFamilies+  build-depends:       base >=4.6 && <5+    , exceptions >= 0.8+    , containers >= 0.5.0.0 && <0.6+    , unordered-containers >= 0.2.0.0 && <0.3+    , transformers >= 0.3 && <0.6+    , transformers-compat+    , free >= 4 && <5+    , hashable+    , mtl+    , profunctors+    , void+    , witherable >= 0.1.3+    , monad-skeleton >= 0.1.1 && <0.3+    , template-haskell+  ghc-options: -Wall+  hs-source-dirs:      src+  default-language:    Haskell2010
src/Control/Object.hs view
@@ -1,20 +1,20 @@------------------------------------------------------------------------------
--- |
--- Module      :  Control.Object
--- Copyright   :  (c) Fumiaki Kinoshita 2015
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Control.Object
-  ( module Control.Object.Object,
-    module Control.Object.Mortal,
-    module Control.Object.Instance,
-  ) where
-
-import Control.Object.Object
-import Control.Object.Mortal
+-----------------------------------------------------------------------------+-- |+-- Module      :  Control.Object+-- Copyright   :  (c) Fumiaki Kinoshita 2015+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Control.Object+  ( module Control.Object.Object,+    module Control.Object.Mortal,+    module Control.Object.Instance,+  ) where++import Control.Object.Object+import Control.Object.Mortal import Control.Object.Instance
src/Control/Object/Instance.hs view
@@ -1,79 +1,79 @@-{-# LANGUAGE GADTs, Rank2Types, LambdaCase #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Object.Instance
--- Copyright   :  (c) Fumiaki Kinoshita 2015
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  provisional
--- Portability :  GADTs, Rank2Types
---
------------------------------------------------------------------------------
-module Control.Object.Instance (
-  -- * Instantiation
-  Instance
-  , new
-  , newSettle
-  -- * Invocation
-  , invokeOnUsing
-  , invokeOn
-  , (.-)
-  , (..-)
-  , (?-)
-  ) where
-import Control.Concurrent
-import Control.Exception (evaluate)
-import Control.Object.Object
-import Control.Monad.IO.Class
-import Control.Monad.Catch
-import Control.Monad.Skeleton
-
-type Instance f g = MVar (Object f g)
-
-invokeOnUsing :: (MonadIO m, MonadMask m)
-  => (Object f g -> t a -> g (a, Object f g))
-  -> (forall x. g x -> m x) -> MVar (Object f g) -> t a -> m a
-invokeOnUsing run m v f = mask $ \restore -> do
-  obj <- liftIO $ takeMVar v
-  (a, obj') <- restore (m (run obj f) >>= liftIO . evaluate) `onException` liftIO (putMVar v obj)
-  liftIO $ putMVar v obj'
-  return a
-
--- | Invoke a method with an explicit landing function.
--- In case of exception, the original object will be set.
-invokeOn :: (MonadIO m, MonadMask m)
-         => (forall x. g x -> m x) -> MVar (Object f g) -> f a -> m a
-invokeOn = invokeOnUsing runObject
-{-# INLINE invokeOn #-}
-
--- | Invoke a method.
-(.-) :: (MonadIO m, MonadMask m) => MVar (Object f m) -> f a -> m a
-(.-) = invokeOn id
-{-# INLINE (.-) #-}
-infixr 3 .-
-
-(..-) :: (MonadIO m, MonadMask m)
-    => MVar (Object t m) -> Skeleton t a -> m a
-(..-) = invokeOnUsing cascadeObject id
-{-# INLINE (..-) #-}
-infixr 3 ..-
-
--- | Try to invoke a method. If the instance is unavailable, it returns Nothing.
-(?-) :: (MonadIO m, MonadMask m) => MVar (Object f m) -> f a -> m (Maybe a)
-v ?- f = mask $ \restore -> liftIO (tryTakeMVar v) >>= \case
-  Just obj -> do
-    (a, obj') <- restore (runObject obj f >>= liftIO . evaluate) `onException` liftIO (putMVar v obj)
-    liftIO $ putMVar v obj'
-    return (Just a)
-  Nothing -> return Nothing
-
--- | Create a new instance. This can be used inside 'unsafePerformIO' to create top-level instances.
-new :: MonadIO m => Object f g -> m (Instance f g)
-new = liftIO . newMVar
-{-# INLINE new #-}
-
--- | Create a new instance, having it sitting on the current environment.
-newSettle :: MonadIO m => Object f m -> m (Instance f m)
-newSettle = new
-{-# INLINE newSettle #-}
+{-# LANGUAGE GADTs, Rank2Types, LambdaCase #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Control.Object.Instance+-- Copyright   :  (c) Fumiaki Kinoshita 2015+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  provisional+-- Portability :  GADTs, Rank2Types+--+-----------------------------------------------------------------------------+module Control.Object.Instance (+  -- * Instantiation+  Instance+  , new+  , newSettle+  -- * Invocation+  , invokeOnUsing+  , invokeOn+  , (.-)+  , (..-)+  , (?-)+  ) where+import Control.Concurrent+import Control.Exception (evaluate)+import Control.Object.Object+import Control.Monad.IO.Class+import Control.Monad.Catch+import Control.Monad.Skeleton++type Instance f g = MVar (Object f g)++invokeOnUsing :: (MonadIO m, MonadMask m)+  => (Object f g -> t a -> g (a, Object f g))+  -> (forall x. g x -> m x) -> Instance f g -> t a -> m a+invokeOnUsing run m v f = mask $ \restore -> do+  obj <- liftIO $ takeMVar v+  (a, obj') <- restore (m (run obj f) >>= liftIO . evaluate) `onException` liftIO (putMVar v obj)+  liftIO $ putMVar v obj'+  return a++-- | Invoke a method with an explicit landing function.+-- In case of exception, the original object will be set.+invokeOn :: (MonadIO m, MonadMask m)+         => (forall x. g x -> m x) -> Instance f g -> f a -> m a+invokeOn = invokeOnUsing runObject+{-# INLINE invokeOn #-}++-- | Invoke a method.+(.-) :: (MonadIO m, MonadMask m) => Instance f m -> f a -> m a+(.-) = invokeOn id+{-# INLINE (.-) #-}+infixr 3 .-++(..-) :: (MonadIO m, MonadMask m)+    => Instance t m -> Skeleton t a -> m a+(..-) = invokeOnUsing cascadeObject id+{-# INLINE (..-) #-}+infixr 3 ..-++-- | Try to invoke a method. If the instance is unavailable, it returns Nothing.+(?-) :: (MonadIO m, MonadMask m) => Instance f m -> f a -> m (Maybe a)+v ?- f = mask $ \restore -> liftIO (tryTakeMVar v) >>= \case+  Just obj -> do+    (a, obj') <- restore (runObject obj f >>= liftIO . evaluate) `onException` liftIO (putMVar v obj)+    liftIO $ putMVar v obj'+    return (Just a)+  Nothing -> return Nothing++-- | Create a new instance. This can be used inside 'unsafePerformIO' to create top-level instances.+new :: MonadIO m => Object f g -> m (Instance f g)+new = liftIO . newMVar+{-# INLINE new #-}++-- | Create a new instance, having it sitting on the current environment.+newSettle :: MonadIO m => Object f m -> m (Instance f m)+newSettle = new+{-# INLINE newSettle #-}
src/Control/Object/Mortal.hs view
@@ -1,115 +1,116 @@-{-# LANGUAGE CPP #-}
-{-# LANGUAGE Trustworthy #-}
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE BangPatterns #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Object.Mortal
--- Copyright   :  (c) Fumiaki Kinoshita 2015
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  provisional
--- Portability :  GADTs, Rank2Types
---
------------------------------------------------------------------------------
-module Control.Object.Mortal (
-    Mortal(..),
-    mortal,
-    mortal_,
-    runMortal,
-    immortal,
-    apprisesOf,
-    apprises,
-    apprise
-    ) where
-
-import Control.Object.Object
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-import Control.Monad.Trans.Either
-import Control.Monad
-import Control.Monad.Trans.Class
-import Control.Monad.Trans.State.Strict
-import Control.Monad.Trans.Writer.Strict
-import Data.Monoid
-import Data.Witherable
-import Data.Tuple (swap)
-import Control.Arrow ((***))
-import Unsafe.Coerce
-
--- | A 'Mortal' is an object that may die.
--- A mortal yields a final result upon death.
--- @'Mortal' f g@ forms a 'Monad':
--- 'return' is a dead object and ('>>=') prolongs the life of the left object.
---
--- @Object f g ≡ Mortal f g Void@
---
-newtype Mortal f g a = Mortal { unMortal :: Object f (EitherT a g) }
-
-instance (Functor m, Monad m) => Functor (Mortal f m) where
-  fmap f (Mortal obj) = Mortal (obj @>>^ bimapEitherT f id)
-  {-# INLINE fmap #-}
-
-instance (Functor m, Monad m) => Applicative (Mortal f m) where
-  pure = return
-  {-# INLINE pure #-}
-  (<*>) = ap
-  {-# INLINE (<*>) #-}
-
-instance Monad m => Monad (Mortal f m) where
-  return a = mortal $ const $ left a
-  {-# INLINE return #-}
-  m >>= k = mortal $ \f -> lift (runEitherT $ runMortal m f) >>= \r -> case r of
-    Left a -> runMortal (k a) f
-    Right (x, m') -> return (x, m' >>= k)
-
-instance MonadTrans (Mortal f) where
-  lift m = mortal $ const $ EitherT $ liftM Left m
-  {-# INLINE lift #-}
-
--- | Construct a mortal in a 'Object' construction manner.
-mortal :: Monad m => (forall x. f x -> EitherT a m (x, Mortal f m a)) -> Mortal f m a
-mortal f = unsafeCoerce f `asTypeOf` Mortal (Object (fmap (fmap unMortal) . f))
-{-# INLINE mortal #-}
-
--- | Send a message to a mortal.
-runMortal :: Monad m => Mortal f m a -> f x -> EitherT a m (x, Mortal f m a)
-runMortal = unsafeCoerce `asTypeOf` ((fmap (fmap Mortal) . ) . runObject . unMortal)
-{-# INLINE runMortal #-}
-
--- | Restricted 'Mortal' constuctor which can be applied to 'transit', 'fromFoldable' without ambiguousness.
-mortal_ :: Object f (EitherT () g) -> Mortal f g ()
-mortal_ = Mortal
-{-# INLINE mortal_ #-}
-
--- | Turn an object into a mortal without death.
-immortal :: Monad m => Object f m -> Mortal f m x
-immortal obj = Mortal (obj @>>^ lift)
-{-# INLINE immortal #-}
-
--- | Send a message to mortals through a filter.
-apprisesOf :: Monad m
-  => FilterLike' (WriterT r m) s (Mortal f m b)
-  -> f a -> (a -> r) -> (b -> r) -> StateT s m r
-apprisesOf l f p q = StateT $ \t -> liftM swap $ runWriterT $ flip l t
-    $ \obj -> WriterT $ runEitherT (runMortal obj f) >>= \case
-      Left r -> return (Nothing, q r)
-      Right (x, obj') -> return (Just obj', p x)
-{-# INLINABLE apprisesOf #-}
-
--- | Send a message to mortals in a 'Witherable' container.
---
--- @apprises = apprisesOf wither@
---
-apprises :: (Witherable t, Monad m, Applicative m, Monoid r) => f a -> (a -> r) -> (b -> r) -> StateT (t (Mortal f m b)) m r
-apprises = apprisesOf wither
-{-# INLINE apprises #-}
-
--- | Send a message to mortals in a container.
-apprise :: (Witherable t, Monad m, Applicative m) => f a -> StateT (t (Mortal f m r)) m ([a], [r])
-apprise f = fmap (flip appEndo [] *** flip appEndo [])
-  $ apprises f (\a -> (Endo (a:), mempty)) (\b -> (mempty, Endo (b:)))
-{-# INLINE apprise #-}
+{-# LANGUAGE CPP #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Control.Object.Mortal+-- Copyright   :  (c) Fumiaki Kinoshita 2015+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  provisional+-- Portability :  GADTs, Rank2Types+--+-----------------------------------------------------------------------------+module Control.Object.Mortal (+    Mortal(..),+    mortal,+    mortal_,+    runMortal,+    immortal,+    apprisesOf,+    apprises,+    apprise+    ) where++import Control.Object.Object+#if !MIN_VERSION_base(4,8,0)+import Control.Applicative+#endif+import Control.Monad.Trans.Except+import Control.Monad+import Control.Monad.Trans.Class+import Control.Monad.Trans.State.Strict+import Control.Monad.Trans.Writer.Strict+import Data.Bifunctor+import Data.Monoid+import Data.Witherable+import Data.Tuple (swap)+import Control.Arrow ((***))+import Unsafe.Coerce++-- | A 'Mortal' is an object that may die.+-- A mortal yields a final result upon death.+-- @'Mortal' f g@ forms a 'Monad':+-- 'return' is a dead object and ('>>=') prolongs the life of the left object.+--+-- @Object f g ≡ Mortal f g Void@+--+newtype Mortal f g a = Mortal { unMortal :: Object f (ExceptT a g) }++instance (Functor m, Monad m) => Functor (Mortal f m) where+  fmap f (Mortal obj) = Mortal (obj @>>^ mapExceptT (fmap (first f)))+  {-# INLINE fmap #-}++instance (Functor m, Monad m) => Applicative (Mortal f m) where+  pure = return+  {-# INLINE pure #-}+  (<*>) = ap+  {-# INLINE (<*>) #-}++instance Monad m => Monad (Mortal f m) where+  return a = mortal $ const $ throwE a+  {-# INLINE return #-}+  m >>= k = mortal $ \f -> lift (runExceptT $ runMortal m f) >>= \r -> case r of+    Left a -> runMortal (k a) f+    Right (x, m') -> return (x, m' >>= k)++instance MonadTrans (Mortal f) where+  lift m = mortal $ const $ ExceptT $ liftM Left m+  {-# INLINE lift #-}++-- | Construct a mortal in a 'Object' construction manner.+mortal :: Monad m => (forall x. f x -> ExceptT a m (x, Mortal f m a)) -> Mortal f m a+mortal f = unsafeCoerce f `asTypeOf` Mortal (Object (fmap (fmap unMortal) . f))+{-# INLINE mortal #-}++-- | Send a message to a mortal.+runMortal :: Monad m => Mortal f m a -> f x -> ExceptT a m (x, Mortal f m a)+runMortal = unsafeCoerce `asTypeOf` ((fmap (fmap Mortal) . ) . runObject . unMortal)+{-# INLINE runMortal #-}++-- | Restricted 'Mortal' constuctor which can be applied to 'transit', 'fromFoldable' without ambiguousness.+mortal_ :: Object f (ExceptT () g) -> Mortal f g ()+mortal_ = Mortal+{-# INLINE mortal_ #-}++-- | Turn an object into a mortal without death.+immortal :: Monad m => Object f m -> Mortal f m x+immortal obj = Mortal (obj @>>^ lift)+{-# INLINE immortal #-}++-- | Send a message to mortals through a filter.+apprisesOf :: Monad m+  => FilterLike' (WriterT r m) s (Mortal f m b)+  -> f a -> (a -> r) -> (b -> r) -> StateT s m r+apprisesOf l f p q = StateT $ \t -> liftM swap $ runWriterT $ flip l t+    $ \obj -> WriterT $ runExceptT (runMortal obj f) >>= \case+      Left r -> return (Nothing, q r)+      Right (x, obj') -> return (Just obj', p x)+{-# INLINABLE apprisesOf #-}++-- | Send a message to mortals in a 'Witherable' container.+--+-- @apprises = apprisesOf wither@+--+apprises :: (Witherable t, Monad m, Applicative m, Monoid r) => f a -> (a -> r) -> (b -> r) -> StateT (t (Mortal f m b)) m r+apprises = apprisesOf wither+{-# INLINE apprises #-}++-- | Send a message to mortals in a container.+apprise :: (Witherable t, Monad m, Applicative m) => f a -> StateT (t (Mortal f m r)) m ([a], [r])+apprise f = fmap (flip appEndo [] *** flip appEndo [])+  $ apprises f (\a -> (Endo (a:), mempty)) (\b -> (mempty, Endo (b:)))+{-# INLINE apprise #-}
src/Control/Object/Object.hs view
@@ -1,240 +1,240 @@-{-# LANGUAGE CPP #-}
-{-# LANGUAGE Rank2Types, TupleSections, TypeOperators #-}
-{-# LANGUAGE GADTs #-}
-#if __GLASGOW_HASKELL__ >= 707
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Object.Object
--- Copyright   :  (c) Fumiaki Kinoshita 2015
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  provisional
--- Portability :  GADTs, Rank2Types
---
------------------------------------------------------------------------------
-module Control.Object.Object (Object(..)
-  , echo
-  , (@>>@)
-  , (@<<@)
-  , liftO
-  , (^>>@)
-  , (@>>^)
-  , (@||@)
-  -- * Stateful construction
-  , unfoldO
-  , unfoldOM
-  , stateful
-  , (@~)
-  , variable
-  -- * Method cascading
-  , (@-)
-  , iterObject
-  , iterative
-  , cascadeObject
-  , cascading
-  -- * Filtering
-  , Fallible(..)
-  , filteredO
-  , filterO
-  -- * Manipulation on StateT
-  , invokesOf
-  , invokes
-  , (@!=)
-  , announce
-  , withBuilder
-  ) where
-import Data.Typeable
-import Control.Monad.Trans.State.Strict
-import Control.Monad.Free
-import Control.Monad
-import Control.Monad.Skeleton
-import Data.Traversable as T
-import Control.Monad.Trans.Writer.Strict
-import Data.Monoid
-import Data.Tuple (swap)
-import qualified Data.Functor.Sum as Functor
-
--- | The type @Object f g@ represents objects which can handle messages @f@, perform actions in the environment @g@.
--- It can be thought of as an automaton that transforms effects.
--- 'Object's can be composed just like functions using '@>>@'; the identity element is 'echo'.
--- Objects are morphisms of the category of actions.
---
--- [/Naturality/]
---     @runObject obj . fmap f ≡ fmap f . runObject obj@
---
-newtype Object f g = Object { runObject :: forall x. f x -> g (x, Object f g) }
-#if __GLASGOW_HASKELL__ >= 707
-  deriving (Typeable)
-#else
-instance (Typeable1 f, Typeable1 g) => Typeable (Object f g) where
-  typeOf t = mkTyConApp objectTyCon [typeOf1 (f t), typeOf1 (g t)] where
-    f :: Object f g -> f a
-    f = undefined
-    g :: Object f g -> g a
-    g = undefined
-
-objectTyCon :: TyCon
-#if __GLASGOW_HASKELL__ < 704
-objectTyCon = mkTyCon "Control.Object.Object"
-#else
-objectTyCon = mkTyCon3 "objective" "Control.Object" "Object"
-#endif
-{-# NOINLINE objectTyCon #-}
-#endif
-
--- | An infix alias for 'runObject'
-(@-) :: Object f g -> f x -> g (x, Object f g)
-(@-) = runObject
-{-# INLINE (@-) #-}
-infixr 3 @-
-
-infixr 1 ^>>@
-infixr 1 @>>^
-
-(^>>@) :: Functor h => (forall x. f x -> g x) -> Object g h -> Object f h
-f ^>>@ m0 = go m0 where go (Object m) = Object $ fmap (fmap go) . m . f
-{-# INLINE (^>>@) #-}
-
-(@>>^) :: Functor h => Object f g -> (forall x. g x -> h x) -> Object f h
-m0 @>>^ g = go m0 where go (Object m) = Object $ fmap (fmap go) . g . m
-{-# INLINE (@>>^) #-}
-
--- | The trivial object
-echo :: Functor f => Object f f
-echo = Object $ fmap (,echo)
-
--- | Lift a natural transformation into an object.
-liftO :: Functor g => (forall x. f x -> g x) -> Object f g
-liftO f = go where go = Object $ fmap (\x -> (x, go)) . f
-{-# INLINE liftO #-}
-
--- | The categorical composition of objects.
-(@>>@) :: Functor h => Object f g -> Object g h -> Object f h
-Object m @>>@ Object n = Object $ fmap (\((x, m'), n') -> (x, m' @>>@ n')) . n . m
-infixr 1 @>>@
-
--- | Reversed '(@>>@)'
-(@<<@) :: Functor h => Object g h -> Object f g -> Object f h
-(@<<@) = flip (@>>@)
-{-# INLINE (@<<@) #-}
-infixl 1 @<<@
-
--- | Combine objects so as to handle a 'Functor.Sum' of interfaces.
-(@||@) :: Functor h => Object f h -> Object g h -> Object (f `Functor.Sum` g) h
-a @||@ b = Object $ \r -> case r of
-  Functor.InL f -> fmap (fmap (@||@b)) (runObject a f)
-  Functor.InR g -> fmap (fmap (a@||@)) (runObject b g)
-
--- | An unwrapped analog of 'stateful'
---     @id = unfoldO runObject@
---     @'iterative' = unfoldO 'iterObject'@
---     @'cascading' = unfoldO 'cascadeObject'@
-unfoldO :: Functor g => (forall a. r -> f a -> g (a, r)) -> r -> Object f g
-unfoldO h = go where go r = Object $ fmap (fmap go) . h r
-{-# INLINE unfoldO #-}
-
--- | Same as 'unfoldO' but requires 'Monad' instead
-unfoldOM :: Monad m => (forall a. r -> f a -> m (a, r)) -> r -> Object f m
-unfoldOM h = go where go r = Object $ liftM (fmap go) . h r
-{-# INLINE unfoldOM #-}
-
--- | Build a stateful object.
---
--- @stateful t s = t ^>>\@ variable s@
---
-stateful :: Monad m => (forall a. t a -> StateT s m a) -> s -> Object t m
-stateful h = go where
-  go s = Object $ \f -> runStateT (h f) s >>= \(a, s') -> s' `seq` return (a, go s')
-{-# INLINE stateful #-}
-
--- | Flipped 'stateful'.
--- it is super convenient to use with the LambdaCase extension.
-(@~) :: Monad m => s -> (forall a. t a -> StateT s m a) -> Object t m
-s @~ h = stateful h s
-{-# INLINE (@~) #-}
-infix 1 @~
-
--- | Cascading
-iterObject :: Monad m => Object f m -> Free f a -> m (a, Object f m)
-iterObject obj (Pure a) = return (a, obj)
-iterObject obj (Free f) = runObject obj f >>= \(cont, obj') -> iterObject obj' cont
-
--- | Objects can consume free monads. 'cascading' is more preferred.
-iterative :: Monad m => Object f m -> Object (Free f) m
-iterative = unfoldOM iterObject
-{-# INLINE iterative #-}
-
--- | A mutable variable.
---
--- @variable = stateful id@
---
-variable :: Monad m => s -> Object (StateT s m) m
-variable = stateful id
-{-# INLINE variable #-}
-
--- | Pass zero or more messages to an object.
-cascadeObject :: Monad m => Object t m -> Skeleton t a -> m (a, Object t m)
-cascadeObject obj sk = case unbone sk of
-  Return a -> return (a, obj)
-  t :>>= k -> runObject obj t >>= \(a, obj') -> cascadeObject obj' (k a)
-
--- | Add capability to handle multiple messages at once.
-cascading :: Monad m => Object t m -> Object (Skeleton t) m
-cascading = unfoldOM cascadeObject
-{-# INLINE cascading #-}
-
--- | Send a message to an object through a lens.
-invokesOf :: Monad m
-  => ((Object t m -> WriterT r m (Object t m)) -> s -> WriterT r m s)
-  -> t a -> (a -> r) -> StateT s m r
-invokesOf t f c = StateT $ liftM swap . runWriterT
-  . t (\obj -> WriterT $ runObject obj f >>= \(x, obj') -> return (obj', c x))
-{-# INLINABLE invokesOf #-}
-
-invokes :: (T.Traversable t, Monad m, Monoid r)
-  => f a -> (a -> r) -> StateT (t (Object f m)) m r
-invokes = invokesOf T.mapM
-{-# INLINE invokes #-}
-
--- | Send a message to objects in a traversable container.
---
--- @announce = withBuilder . invokesOf traverse@
---
-announce :: (T.Traversable t, Monad m) => f a -> StateT (t (Object f m)) m [a]
-announce f = withBuilderM (invokes f)
-{-# INLINABLE announce #-}
-
--- | A method invocation operator on 'StateT'.
-(@!=) :: Monad m
-  => ((Object t m -> WriterT a m (Object t m)) -> s -> WriterT a m s)
-  -> t a -> StateT s m a
-l @!= f = invokesOf l f id
-{-# INLINE (@!=) #-}
-
-withBuilder :: Functor f => ((a -> Endo [a]) -> f (Endo [a])) -> f [a]
-withBuilder f = fmap (flip appEndo []) (f (Endo . (:)))
-{-# INLINABLE withBuilder #-}
-
-withBuilderM :: Monad f => ((a -> Endo [a]) -> f (Endo [a])) -> f [a]
-withBuilderM f = liftM (flip appEndo []) (f (Endo . (:)))
-{-# INLINABLE withBuilderM #-}
-
-data Fallible t a where
-  Fallible :: t a -> Fallible t (Maybe a)
-
-filteredO :: Monad m
-       => (forall x. t x -> Bool)
-       -> Object t m -> Object (Fallible t) m
-filteredO p obj = Object $ \(Fallible t) -> if p t
-  then runObject obj t >>= \(a, obj') -> return (Just a, filteredO p obj')
-  else return (Nothing, filteredO p obj)
-
-filterO :: (forall x. t x -> Bool) -> Object (Fallible t) (Skeleton t)
-filterO p = filteredO p (liftO bone)
-{-# INLINE filterO #-}
+{-# LANGUAGE CPP #-}+{-# LANGUAGE Rank2Types, TupleSections, TypeOperators #-}+{-# LANGUAGE GADTs #-}+#if __GLASGOW_HASKELL__ >= 707+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE Safe #-}+#else+{-# LANGUAGE Trustworthy #-}+#endif+-----------------------------------------------------------------------------+-- |+-- Module      :  Control.Object.Object+-- Copyright   :  (c) Fumiaki Kinoshita 2015+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  provisional+-- Portability :  GADTs, Rank2Types+--+-----------------------------------------------------------------------------+module Control.Object.Object (Object(..)+  , echo+  , (@>>@)+  , (@<<@)+  , liftO+  , (^>>@)+  , (@>>^)+  , (@||@)+  -- * Stateful construction+  , unfoldO+  , unfoldOM+  , stateful+  , (@~)+  , variable+  -- * Method cascading+  , (@-)+  , iterObject+  , iterative+  , cascadeObject+  , cascading+  -- * Filtering+  , Fallible(..)+  , filteredO+  , filterO+  -- * Manipulation on StateT+  , invokesOf+  , invokes+  , (@!=)+  , announce+  , withBuilder+  ) where+import Data.Typeable+import Control.Monad.Trans.State.Strict+import Control.Monad.Free+import Control.Monad+import Control.Monad.Skeleton+import Data.Traversable as T+import Control.Monad.Trans.Writer.Strict+import Data.Monoid+import Data.Tuple (swap)+import qualified Data.Functor.Sum as Functor++-- | The type @Object f g@ represents objects which can handle messages @f@, perform actions in the environment @g@.+-- It can be thought of as an automaton that transforms effects.+-- 'Object's can be composed just like functions using '@>>@'; the identity element is 'echo'.+-- Objects are morphisms of the category of actions.+--+-- [/Naturality/]+--     @runObject obj . fmap f ≡ fmap f . runObject obj@+--+newtype Object f g = Object { runObject :: forall x. f x -> g (x, Object f g) }+#if __GLASGOW_HASKELL__ >= 707+  deriving (Typeable)+#else+instance (Typeable1 f, Typeable1 g) => Typeable (Object f g) where+  typeOf t = mkTyConApp objectTyCon [typeOf1 (f t), typeOf1 (g t)] where+    f :: Object f g -> f a+    f = undefined+    g :: Object f g -> g a+    g = undefined++objectTyCon :: TyCon+#if __GLASGOW_HASKELL__ < 704+objectTyCon = mkTyCon "Control.Object.Object"+#else+objectTyCon = mkTyCon3 "objective" "Control.Object" "Object"+#endif+{-# NOINLINE objectTyCon #-}+#endif++-- | An infix alias for 'runObject'+(@-) :: Object f g -> f x -> g (x, Object f g)+(@-) = runObject+{-# INLINE (@-) #-}+infixr 3 @-++infixr 1 ^>>@+infixr 1 @>>^++(^>>@) :: Functor h => (forall x. f x -> g x) -> Object g h -> Object f h+f ^>>@ m0 = go m0 where go (Object m) = Object $ fmap (fmap go) . m . f+{-# INLINE (^>>@) #-}++(@>>^) :: Functor h => Object f g -> (forall x. g x -> h x) -> Object f h+m0 @>>^ g = go m0 where go (Object m) = Object $ fmap (fmap go) . g . m+{-# INLINE (@>>^) #-}++-- | The trivial object+echo :: Functor f => Object f f+echo = Object $ fmap (,echo)++-- | Lift a natural transformation into an object.+liftO :: Functor g => (forall x. f x -> g x) -> Object f g+liftO f = go where go = Object $ fmap (\x -> (x, go)) . f+{-# INLINE liftO #-}++-- | The categorical composition of objects.+(@>>@) :: Functor h => Object f g -> Object g h -> Object f h+Object m @>>@ Object n = Object $ fmap (\((x, m'), n') -> (x, m' @>>@ n')) . n . m+infixr 1 @>>@++-- | Reversed '(@>>@)'+(@<<@) :: Functor h => Object g h -> Object f g -> Object f h+(@<<@) = flip (@>>@)+{-# INLINE (@<<@) #-}+infixl 1 @<<@++-- | Combine objects so as to handle a 'Functor.Sum' of interfaces.+(@||@) :: Functor h => Object f h -> Object g h -> Object (f `Functor.Sum` g) h+a @||@ b = Object $ \r -> case r of+  Functor.InL f -> fmap (fmap (@||@b)) (runObject a f)+  Functor.InR g -> fmap (fmap (a@||@)) (runObject b g)++-- | An unwrapped analog of 'stateful'+--     @id = unfoldO runObject@+--     @'iterative' = unfoldO 'iterObject'@+--     @'cascading' = unfoldO 'cascadeObject'@+unfoldO :: Functor g => (forall a. r -> f a -> g (a, r)) -> r -> Object f g+unfoldO h = go where go r = Object $ fmap (fmap go) . h r+{-# INLINE unfoldO #-}++-- | Same as 'unfoldO' but requires 'Monad' instead+unfoldOM :: Monad m => (forall a. r -> f a -> m (a, r)) -> r -> Object f m+unfoldOM h = go where go r = Object $ liftM (fmap go) . h r+{-# INLINE unfoldOM #-}++-- | Build a stateful object.+--+-- @stateful t s = t ^>>\@ variable s@+--+stateful :: Monad m => (forall a. t a -> StateT s m a) -> s -> Object t m+stateful h = go where+  go s = Object $ \f -> runStateT (h f) s >>= \(a, s') -> s' `seq` return (a, go s')+{-# INLINE stateful #-}++-- | Flipped 'stateful'.+-- it is super convenient to use with the LambdaCase extension.+(@~) :: Monad m => s -> (forall a. t a -> StateT s m a) -> Object t m+s @~ h = stateful h s+{-# INLINE (@~) #-}+infix 1 @~++-- | Cascading+iterObject :: Monad m => Object f m -> Free f a -> m (a, Object f m)+iterObject obj (Pure a) = return (a, obj)+iterObject obj (Free f) = runObject obj f >>= \(cont, obj') -> iterObject obj' cont++-- | Objects can consume free monads. 'cascading' is more preferred.+iterative :: Monad m => Object f m -> Object (Free f) m+iterative = unfoldOM iterObject+{-# INLINE iterative #-}++-- | A mutable variable.+--+-- @variable = stateful id@+--+variable :: Monad m => s -> Object (StateT s m) m+variable = stateful id+{-# INLINE variable #-}++-- | Pass zero or more messages to an object.+cascadeObject :: Monad m => Object t m -> Skeleton t a -> m (a, Object t m)+cascadeObject obj sk = case debone sk of+  Return a -> return (a, obj)+  t :>>= k -> runObject obj t >>= \(a, obj') -> cascadeObject obj' (k a)++-- | Add capability to handle multiple messages at once.+cascading :: Monad m => Object t m -> Object (Skeleton t) m+cascading = unfoldOM cascadeObject+{-# INLINE cascading #-}++-- | Send a message to an object through a lens.+invokesOf :: Monad m+  => ((Object t m -> WriterT r m (Object t m)) -> s -> WriterT r m s)+  -> t a -> (a -> r) -> StateT s m r+invokesOf t f c = StateT $ liftM swap . runWriterT+  . t (\obj -> WriterT $ runObject obj f >>= \(x, obj') -> return (obj', c x))+{-# INLINABLE invokesOf #-}++invokes :: (T.Traversable t, Monad m, Monoid r)+  => f a -> (a -> r) -> StateT (t (Object f m)) m r+invokes = invokesOf T.mapM+{-# INLINE invokes #-}++-- | Send a message to objects in a traversable container.+--+-- @announce = withBuilder . invokesOf traverse@+--+announce :: (T.Traversable t, Monad m) => f a -> StateT (t (Object f m)) m [a]+announce f = withBuilderM (invokes f)+{-# INLINABLE announce #-}++-- | A method invocation operator on 'StateT'.+(@!=) :: Monad m+  => ((Object t m -> WriterT a m (Object t m)) -> s -> WriterT a m s)+  -> t a -> StateT s m a+l @!= f = invokesOf l f id+{-# INLINE (@!=) #-}++withBuilder :: Functor f => ((a -> Endo [a]) -> f (Endo [a])) -> f [a]+withBuilder f = fmap (flip appEndo []) (f (Endo . (:)))+{-# INLINABLE withBuilder #-}++withBuilderM :: Monad f => ((a -> Endo [a]) -> f (Endo [a])) -> f [a]+withBuilderM f = liftM (flip appEndo []) (f (Endo . (:)))+{-# INLINABLE withBuilderM #-}++data Fallible t a where+  Fallible :: t a -> Fallible t (Maybe a)++filteredO :: Monad m+       => (forall x. t x -> Bool)+       -> Object t m -> Object (Fallible t) m+filteredO p obj = Object $ \(Fallible t) -> if p t+  then runObject obj t >>= \(a, obj') -> return (Just a, filteredO p obj')+  else return (Nothing, filteredO p obj)++filterO :: (forall x. t x -> Bool) -> Object (Fallible t) (Skeleton t)+filterO p = filteredO p (liftO bone)+{-# INLINE filterO #-}
src/Data/Functor/Request.hs view
@@ -1,93 +1,93 @@-{-# LANGUAGE CPP, DeriveFunctor, DeriveDataTypeable, ConstraintKinds, FlexibleContexts, TypeOperators, DataKinds, TypeFamilies #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Functor.Request
--- Copyright   :  (c) Fumiaki Kinoshita 2015
--- License     :  BSD3
---
--- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Data.Functor.Request where
-import Data.Typeable
-#if !MIN_VERSION_base(4,8,0)
-import Data.Monoid
-#endif
-import Control.Applicative
-import Data.Profunctor
-import Control.Object.Object
-import qualified Data.HashMap.Strict as HM
-import Data.Hashable
-import Control.Arrow
-
--- | @'Request' a b@ is the type of a request that sends @a@ to receive @b@.
-data Request a b r = Request a (b -> r) deriving (Functor, Typeable)
-
--- | Apply a function to the body of 'Request'
-mapRequest :: (a -> a') -> Request a b r -> Request a' b r
-mapRequest f (Request a br) = Request (f a) br
-{-# INLINE mapRequest #-}
-
-instance Profunctor (Request a) where
-  dimap f g (Request a br) = Request a (dimap f g br)
-  {-# INLINE dimap #-}
-
-instance Monoid a => Applicative (Request a b) where
-  pure a = Request mempty (const a)
-  {-# INLINE pure #-}
-  Request a c <*> Request b d = Request (mappend a b) (c <*> d)
-  {-# INLINE (<*>) #-}
-
--- | Create a 'Request'.
-request :: a -> Request a b b
-request a = Request a id
-{-# INLINE request #-}
-
--- | Handle a 'Request', smashing the continuation.
-accept :: Functor m => (a -> m b) -> Request a b r -> m r
-accept f = \(Request a cont) -> cont <$> f a
-{-# INLINE accept #-}
-
--- | Add a step as a mealy machine
-mealy :: Functor m => (a -> m (b, Object (Request a b) m)) -> Object (Request a b) m
-mealy f = Object $ \(Request a cont) -> first cont <$> f a
-{-# INLINE mealy #-}
-
--- | The flyweight object
-flyweight :: (Applicative m, Eq k, Hashable k) => (k -> m a) -> Object (Request k a) m
-flyweight f = go HM.empty where
-  go m = mealy $ \k -> case HM.lookup k m of
-    Just a -> pure (a, go m)
-    Nothing -> (\a -> (a, go $ HM.insert k a m)) <$> f k
-{-# INLINE flyweight #-}
-
--- | Compose mealy machines
-(>~~>) :: Monad m => Object (Request a b) m -> Object (Request b c) m -> Object (Request a c) m
-p >~~> q = Object $ \(Request a cont) -> do
-  (b, p') <- runObject p (Request a id)
-  (r, q') <- runObject q (Request b cont)
-  return (r, p' >~~> q')
-
-accumulator :: Applicative m => (b -> a -> b) -> b -> Object (Request a b) m
-accumulator f = go where
-  go b = mealy $ \a -> pure (b, go (f b a))
-{-# INLINE accumulator #-}
-
--- | Create a mealy machine from a time-varying action.
---
--- @ animate f ≡ accumulator (+) 0 >~~> liftO (accept f)@
---
-animate :: (Applicative m, Num t) => (t -> m a) -> Object (Request t a) m
-animate f = go 0 where
-  go t = mealy $ \dt -> flip (,) (go (t + dt)) <$> f t
-{-# INLINE animate #-}
-
--- | Like 'animate', but the life is limited.
-transit :: (Alternative m, Fractional t, Ord t) => t -> (t -> m a) -> Object (Request t a) m
-transit len f = animate go where
-  go t
-    | t >= len = empty
-    | otherwise = f (t / len)
-{-# INLINE transit #-}
+{-# LANGUAGE CPP, DeriveFunctor, DeriveDataTypeable, ConstraintKinds, FlexibleContexts, TypeOperators, DataKinds, TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  Data.Functor.Request+-- Copyright   :  (c) Fumiaki Kinoshita 2015+-- License     :  BSD3+--+-- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>+-- Stability   :  experimental+-- Portability :  non-portable+--+-----------------------------------------------------------------------------+module Data.Functor.Request where+import Data.Typeable+#if !MIN_VERSION_base(4,8,0)+import Data.Monoid+#endif+import Control.Applicative+import Data.Profunctor+import Control.Object.Object+import qualified Data.HashMap.Strict as HM+import Data.Hashable+import Control.Arrow++-- | @'Request' a b@ is the type of a request that sends @a@ to receive @b@.+data Request a b r = Request a (b -> r) deriving (Functor, Typeable)++-- | Apply a function to the body of 'Request'+mapRequest :: (a -> a') -> Request a b r -> Request a' b r+mapRequest f (Request a br) = Request (f a) br+{-# INLINE mapRequest #-}++instance Profunctor (Request a) where+  dimap f g (Request a br) = Request a (dimap f g br)+  {-# INLINE dimap #-}++instance Monoid a => Applicative (Request a b) where+  pure a = Request mempty (const a)+  {-# INLINE pure #-}+  Request a c <*> Request b d = Request (mappend a b) (c <*> d)+  {-# INLINE (<*>) #-}++-- | Create a 'Request'.+request :: a -> Request a b b+request a = Request a id+{-# INLINE request #-}++-- | Handle a 'Request', smashing the continuation.+accept :: Functor m => (a -> m b) -> Request a b r -> m r+accept f = \(Request a cont) -> cont <$> f a+{-# INLINE accept #-}++-- | Add a step as a mealy machine+mealy :: Functor m => (a -> m (b, Object (Request a b) m)) -> Object (Request a b) m+mealy f = Object $ \(Request a cont) -> first cont <$> f a+{-# INLINE mealy #-}++-- | The flyweight object+flyweight :: (Applicative m, Eq k, Hashable k) => (k -> m a) -> Object (Request k a) m+flyweight f = go HM.empty where+  go m = mealy $ \k -> case HM.lookup k m of+    Just a -> pure (a, go m)+    Nothing -> (\a -> (a, go $ HM.insert k a m)) <$> f k+{-# INLINE flyweight #-}++-- | Compose mealy machines+(>~~>) :: Monad m => Object (Request a b) m -> Object (Request b c) m -> Object (Request a c) m+p >~~> q = Object $ \(Request a cont) -> do+  (b, p') <- runObject p (Request a id)+  (r, q') <- runObject q (Request b cont)+  return (r, p' >~~> q')++accumulator :: Applicative m => (b -> a -> b) -> b -> Object (Request a b) m+accumulator f = go where+  go b = mealy $ \a -> pure (b, go (f b a))+{-# INLINE accumulator #-}++-- | Create a mealy machine from a time-varying action.+--+-- @ animate f ≡ accumulator (+) 0 >~~> liftO (accept f)@+--+animate :: (Applicative m, Num t) => (t -> m a) -> Object (Request t a) m+animate f = go 0 where+  go t = mealy $ \dt -> flip (,) (go (t + dt)) <$> f t+{-# INLINE animate #-}++-- | Like 'animate', but the life is limited.+transit :: (Alternative m, Fractional t, Ord t) => t -> (t -> m a) -> Object (Request t a) m+transit len f = animate go where+  go t+    | t >= len = empty+    | otherwise = f (t / len)+{-# INLINE transit #-}