free 4.7 → 4.7.1
raw patch · 6 files changed
+72/−9 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.Monad.Free: cutoff :: Functor f => Integer -> Free f a -> Free f (Maybe a)
+ Control.Monad.Trans.Free: cutoff :: (Functor f, Monad m) => Integer -> FreeT f m a -> FreeT f m (Maybe a)
+ Control.Monad.Trans.Free.Church: cutoff :: (Functor f, Monad m) => Integer -> FT f m a -> FT f m (Maybe a)
Files
- CHANGELOG.markdown +4/−0
- free.cabal +1/−1
- src/Control/Monad/Free.hs +19/−0
- src/Control/Monad/Trans/Free.hs +20/−0
- src/Control/Monad/Trans/Free/Church.hs +18/−0
- src/Control/Monad/Trans/Iter.hs +10/−8
CHANGELOG.markdown view
@@ -1,3 +1,7 @@+4.7.1+-----+* Added more versions of `cutoff`.+ 4.7 --- * Added `prelude-extras` support. This makes it possible to work without `UndecidableInstances` for most operations.
free.cabal view
@@ -1,6 +1,6 @@ name: free category: Control, Monads-version: 4.7+version: 4.7.1 license: BSD3 cabal-version: >= 1.10 license-file: LICENSE
src/Control/Monad/Free.hs view
@@ -28,6 +28,7 @@ , iterM , hoistFree , toFreeT+ , cutoff , _Pure, _Free ) where @@ -293,6 +294,24 @@ toFreeT :: (Functor f, Monad m) => Free f a -> FreeT.FreeT f m a toFreeT (Pure a) = FreeT.FreeT (return (FreeT.Pure a)) toFreeT (Free f) = FreeT.FreeT (return (FreeT.Free (fmap toFreeT f)))++-- | Cuts off a tree of computations at a given depth.+-- If the depth is 0 or less, no computation nor+-- monadic effects will take place.+--+-- Some examples (n ≥ 0):+--+-- prop> cutoff 0 _ == return Nothing+-- prop> cutoff (n+1) . return == return . Just+-- prop> cutoff (n+1) . lift == lift . liftM Just+-- prop> cutoff (n+1) . wrap == wrap . fmap (cutoff n)+--+-- Calling 'retract . cutoff n' is always terminating, provided each of the+-- steps in the iteration is terminating.+cutoff :: (Functor f) => Integer -> Free f a -> Free f (Maybe a)+cutoff 0 _ = return Nothing+cutoff n (Free f) = Free $ fmap (cutoff (n - 1)) f+cutoff _ m = Just <$> m -- | This is @Prism' (Free f a) a@ in disguise --
src/Control/Monad/Trans/Free.hs view
@@ -39,6 +39,7 @@ , iterTM , hoistFreeT , transFreeT+ , cutoff -- * Operations of free monad , retract , iter@@ -331,6 +332,25 @@ -- | Like 'iter' for monadic values. iterM :: (Functor f, Monad m) => (f (m a) -> m a) -> Free f a -> m a iterM phi = iterT phi . hoistFreeT (return . runIdentity)++-- | Cuts off a tree of computations at a given depth.+-- If the depth is @0@ or less, no computation nor+-- monadic effects will take place.+--+-- Some examples (@n ≥ 0@):+--+-- @+-- 'cutoff' 0 _ ≡ 'return' 'Nothing'+-- 'cutoff' (n+1) '.' 'return' ≡ 'return' '.' 'Just'+-- 'cutoff' (n+1) '.' 'lift' ≡ 'lift' '.' 'liftM' 'Just'+-- 'cutoff' (n+1) '.' 'wrap' ≡ 'wrap' '.' 'fmap' ('cutoff' n)+-- @+--+-- Calling @'retract' '.' 'cutoff' n@ is always terminating, provided each of the+-- steps in the iteration is terminating.+cutoff :: (Functor f, Monad m) => Integer -> FreeT f m a -> FreeT f m (Maybe a)+cutoff 0 _ = return Nothing+cutoff n (FreeT m) = FreeT $ bimap Just (cutoff (n - 1)) `liftM` m #if __GLASGOW_HASKELL__ < 707 instance Typeable1 f => Typeable2 (FreeF f) where
src/Control/Monad/Trans/Free/Church.hs view
@@ -33,6 +33,7 @@ , iterTM , hoistFT , transFT+ , cutoff -- * Operations of free monad , improve , fromF, toF@@ -55,6 +56,7 @@ import Control.Monad.Cont.Class import Control.Monad.Free.Class import Control.Monad.Trans.Free (FreeT(..), FreeF(..), Free)+import qualified Control.Monad.Trans.Free as FreeT import Data.Foldable (Foldable) import qualified Data.Foldable as F import Data.Traversable (Traversable)@@ -192,6 +194,22 @@ -- | Lift a natural transformation from @f@ to @g@ into a monad homomorphism from @'FT' f m@ to @'FT' g n@ transFT :: (Monad m, Functor g) => (forall a. f a -> g a) -> FT f m b -> FT g m b transFT phi (FT m) = FT (\kp kf -> m kp (kf . phi))++-- | Cuts off a tree of computations at a given depth.+-- If the depth is 0 or less, no computation nor+-- monadic effects will take place.+--+-- Some examples (n ≥ 0):+--+-- prop> cutoff 0 _ == return Nothing+-- prop> cutoff (n+1) . return == return . Just+-- prop> cutoff (n+1) . lift == lift . liftM Just+-- prop> cutoff (n+1) . wrap == wrap . fmap (cutoff n)+--+-- Calling 'retract . cutoff n' is always terminating, provided each of the+-- steps in the iteration is terminating.+cutoff :: (Functor f, Monad m) => Integer -> FT f m a -> FT f m (Maybe a)+cutoff n = toFT . FreeT.cutoff n . fromFT -- | -- 'retract' is the left inverse of 'liftF'
src/Control/Monad/Trans/Iter.hs view
@@ -303,15 +303,17 @@ -- -- The step where the final value is produced also counts towards the limit. ----- Some examples (n ≥ 0):+-- Some examples (@n ≥ 0@): ----- prop> cutoff 0 _ == return Nothing--- prop> cutoff (n+1) . return == return . Just--- prop> cutoff (n+1) . lift == lift . liftM Just--- prop> cutoff (n+1) . delay == delay . cutoff n--- prop> cutoff n never == iterate delay (return Nothing) !! n+-- @+-- 'cutoff' 0 _ ≡ 'return' 'Nothing'+-- 'cutoff' (n+1) '.' 'return' ≡ 'return' '.' 'Just'+-- 'cutoff' (n+1) '.' 'lift' ≡ 'lift' '.' 'liftM' 'Just'+-- 'cutoff' (n+1) '.' 'delay' ≡ 'delay' . 'cutoff' n+-- 'cutoff' n 'never' ≡ 'iterate' 'delay' ('return' 'Nothing') '!!' n+-- @ ----- Calling 'retract . cutoff n' is always terminating, provided each of the+-- Calling @'retract' '.' 'cutoff' n@ is always terminating, provided each of the -- steps in the iteration is terminating. cutoff :: (Monad m) => Integer -> IterT m a -> IterT m (Maybe a) cutoff n | n <= 0 = const $ return Nothing@@ -337,7 +339,7 @@ -- The resulting computation has as many steps as the longest computation -- in the list. ----- Equivalent to @void . interleave@.+-- Equivalent to @'void' '.' 'interleave'@. interleave_ :: (Monad m) => [IterT m a] -> IterT m () interleave_ [] = return () interleave_ xs = IterT $ liftM (Right . interleave_ . rights) $ mapM runIterT xs