monad-skeleton 0.1.5 → 0.2
raw patch · 7 files changed
+57/−130 lines, 7 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Control.Monad.Skeleton: unbone :: Skeleton t a -> MonadView t (Skeleton t) a
+ Control.Monad.Skeleton: infixl 1 :>>=
+ Control.Monad.Zombie: disembalmBy :: r -> (MonadView t (Zombie t) a -> r -> r) -> Zombie t a -> r
- Control.Monad.Skeleton: [:>>=] :: !(t a) -> (a -> m b) -> MonadView t m b
+ Control.Monad.Skeleton: [:>>=] :: !t a -> (a -> m b) -> MonadView t m b
Files
- .travis.yml +0/−85
- CHANGELOG.md +3/−3
- README.md +1/−1
- monad-skeleton.cabal +8/−8
- src/Control/Monad/Skeleton.hs +13/−19
- src/Control/Monad/Skeleton/Internal.hs +7/−1
- src/Control/Monad/Zombie.hs +25/−13
− .travis.yml
@@ -1,85 +0,0 @@-# This file has been generated -- see https://github.com/hvr/multi-ghc-travis-language: c-sudo: false--cache:- directories:- - $HOME/.cabsnap- - $HOME/.cabal/packages--before_cache:- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log- - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar--matrix:- include:- - env: CABALVER=1.18 GHCVER=7.8.4- compiler: ": #GHC 7.8.4"- addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}- - env: CABALVER=1.22 GHCVER=7.10.3- compiler: ": #GHC 7.10.3"- addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}- - env: CABALVER=1.24 GHCVER=8.0.2- compiler: ": #GHC 8.0.2"- addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}}- - env: CABALVER=head GHCVER=head- addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}- allow_failures:- - env: CABALVER=head GHCVER=head-before_install:- - unset CC- - 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 '?')]"- - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];- then- zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >- $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;- fi- - travis_retry cabal update -v- - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config- - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt- - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt--# check whether current requested install-plan matches cached package-db snapshot- - if diff -u $HOME/.cabsnap/installplan.txt installplan.txt;- then- echo "cabal build-cache HIT";- rm -rfv .ghc;- cp -a $HOME/.cabsnap/ghc $HOME/.ghc;- cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;- else- echo "cabal build-cache MISS";- rm -rf $HOME/.cabsnap;- mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;- cabal install --only-dependencies --enable-tests --enable-benchmarks;- fi--# snapshot package-db on cache miss- - if [ ! -d $HOME/.cabsnap ];- then- echo "snapshotting package-db to build-cache";- mkdir $HOME/.cabsnap;- cp -a $HOME/.ghc $HOME/.cabsnap/ghc;- cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;- fi--# 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- - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging- - cabal build # this builds all libraries and executables (including tests/benchmarks)- - cabal test- - cabal check- - cabal sdist # tests that a source-distribution can be generated--# Check that the resulting source distribution can be built & installed.-# If there are no other `.tar.gz` files in `dist`, this can be even simpler:-# `cabal install --force-reinstalls dist/*-*.tar.gz`- - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&- (cd dist && cabal install --force-reinstalls "$SRC_TGZ")--# EOF
CHANGELOG.md view
@@ -1,7 +1,7 @@-0.1.5+0.2 -----* Changed the representation of `Zombie` too-* Added `deboneBy`++* Removed `unbone` 0.1.4 ----
README.md view
@@ -4,7 +4,7 @@ [](https://travis-ci.org/fumieval/monad-skeleton) [](https://hackage.haskell.org/package/monad-skeleton) -This package provides `Skeleton`, an operational monad. The internal encoding+This package provides `Skeleton`, an operational monad (i.e. free monad that does not require the Functor implementation). The internal encoding gives O(1) bind and monadic reflection. `Skeleton` promotes unit instructions to a monad. It is isomorphic to
monad-skeleton.cabal view
@@ -1,23 +1,23 @@+cabal-version: 2.4 name: monad-skeleton-version: 0.1.5+version: 0.2 synopsis: Monads of program skeleta description: Fast operational monad library homepage: https://github.com/fumieval/monad-skeleton bug-reports: http://github.com/fumieval/monad-skeleton/issues-license: BSD3+license: BSD-3-Clause license-file: LICENSE author: Fumiaki Kinoshita maintainer: Fumiaki Kinoshita <fumiexcel@gmail.com>-copyright: Copyright (c) 2017 Fumiaki Kinoshita+copyright: Copyright (c) 2021 Fumiaki Kinoshita category: Control, Monads build-type: Simple-cabal-version: >=1.10+ extra-source-files:- .travis.yml .gitignore README.md CHANGELOG.md-tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2+tested-with: GHC == 8.10.7, GHC == 9.2.1 source-repository head type: git@@ -27,7 +27,7 @@ exposed-modules: Control.Monad.Skeleton , Control.Monad.Skeleton.Internal , Control.Monad.Zombie- build-depends: base == 4.*+ build-depends: base >= 4.9 && <4.17 hs-source-dirs: src- ghc-options: -Wall+ ghc-options: -Wall -Wcompat default-language: Haskell2010
src/Control/Monad/Skeleton.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE BangPatterns, RankNTypes, GADTs, ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-} module Control.Monad.Skeleton (MonadView(..) , hoistMV , iterMV@@ -6,7 +8,6 @@ , bone , debone , deboneBy- , unbone , boned , hoistSkeleton ) where@@ -17,13 +18,13 @@ import Control.Monad.Skeleton.Internal import Prelude hiding (id, (.)) --- | Re-add a bone.+-- | Re-add a bone. Inverse of 'debone' boned :: MonadView t (Skeleton t) a -> Skeleton t a boned (Return a) = ReturnS a boned (t :>>= k) = BindS t $ Leaf $ Kleisli k {-# INLINE boned #-} --- | Pick a bone from a 'Skeleton'.+-- | Extract the first instruction in 'Skeleton'. debone :: Skeleton t a -> MonadView t (Skeleton t) a debone (ReturnS a) = Return a debone (BindS t c0) = t :>>= go c0 where@@ -32,8 +33,8 @@ ReturnS b -> go c' b BindS t' c'' -> BindS t' (Tree c'' c') --- | Pick a bone from a 'Skeleton' by a function.--- It's useful when used with @LambdaCase@.+-- | Continuation-passing variant of 'debone'+-- which allows nicer expression using @LambdaCase@. -- -- Usecase: --@@ -45,12 +46,6 @@ deboneBy f s = f (debone s) {-# INLINE deboneBy #-} --- | Uncommon synonym for 'debone'.-unbone :: Skeleton t a -> MonadView t (Skeleton t) a-unbone = debone-{-# INLINE unbone #-}-{-# DEPRECATED unbone "Use debone instead" #-}- -- | A skeleton that has only one bone. bone :: t a -> Skeleton t a bone t = BindS t $ Leaf $ Kleisli ReturnS@@ -75,7 +70,7 @@ fmap f (t :>>= k) = t :>>= fmap f . k {-# INLINE fmap #-} --- | Transform the action and the continuation.+-- | Transform the instruction as well as the continuation. hoistMV :: (forall x. s x -> t x) -> (m a -> n a) -> MonadView s m a -> MonadView t n a hoistMV _ _ (Return a) = Return a hoistMV f g (t :>>= k) = f t :>>= g . k@@ -90,8 +85,8 @@ {-# INLINE iterMV #-} -- | @'Skeleton' t@ is a monadic skeleton (operational monad) made out of 't'.--- Skeletons can be fleshed out by getting transformed to other monads.--- It provides O(1) ('>>=') and 'debone', the monadic reflection.+-- Skeletons can be fleshed out by interpreting the instructions.+-- It provides O(1) ('>>=') and 'debone'. data Skeleton t a where ReturnS :: a -> Skeleton t a BindS :: t a -> Cat (Kleisli (Skeleton t)) a b -> Skeleton t b@@ -101,15 +96,14 @@ {-# INLINE fmap #-} instance Applicative (Skeleton t) where- pure = return+ pure = ReturnS {-# INLINE pure #-} (<*>) = ap {-# INLINE (<*>) #-}- (*>) = (>>)- {-# INLINE (*>) #-}+ ReturnS _ *> k = k+ BindS t c *> k = BindS t (c |> Kleisli (const k)) a <* b = a >>= \x -> b >> return x instance Monad (Skeleton t) where- return = ReturnS ReturnS a >>= k = k a BindS t c >>= k = BindS t (c |> Kleisli k)
src/Control/Monad/Skeleton/Internal.hs view
@@ -1,9 +1,14 @@-{-# LANGUAGE PolyKinds, GADTs, Rank2Types, ScopedTypeVariables, Trustworthy #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Trustworthy #-} module Control.Monad.Skeleton.Internal (Cat(..), transCat, (|>), viewL, transKleisli) where import Control.Arrow import Unsafe.Coerce +-- | Type-aligned catenable queue data Cat k a b where Leaf :: k a b -> Cat k a b Tree :: Cat k a b -> Cat k b c -> Cat k a c@@ -17,6 +22,7 @@ s |> k = Tree s (Leaf k) {-# INLINE (|>) #-} +-- | Match on the leftmost element. It gradually rotates the nodes so that following calls to 'viewL' is faster. viewL :: forall k a b r. Cat k a b -> (k a b -> r) -> (forall x. k a x -> Cat k x b -> r)
src/Control/Monad/Zombie.hs view
@@ -1,8 +1,11 @@-{-# LANGUAGE Rank2Types, ScopedTypeVariables, GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-} module Control.Monad.Zombie (Zombie(..) , liftZ , embalm , disembalm+ , disembalmBy , hoistZombie ) where import Control.Applicative@@ -22,9 +25,11 @@ fmap = liftM instance Applicative (Zombie t) where- pure = return+ pure a = ReturnZ a Sunlight (<*>) = ap- (*>) = (>>)+ Sunlight *> _ = Sunlight+ ReturnZ _ xs *> k = k <|> (xs *> k)+ BindZ x c xs *> k = BindZ x (c |> Kleisli (const k)) (xs *> k) instance Alternative (Zombie t) where empty = Sunlight@@ -33,7 +38,6 @@ BindZ x c xs <|> ys = BindZ x c (xs <|> ys) instance Monad (Zombie t) where- return a = ReturnZ a Sunlight Sunlight >>= _ = Sunlight ReturnZ a xs >>= k = k a <|> (xs >>= k) BindZ x c xs >>= k = BindZ x (c |> Kleisli k) (xs >>= k)@@ -55,18 +59,26 @@ -- | Decompose a zombie as a list of possibilities. disembalm :: Zombie t a -> [MonadView t (Zombie t) a]-disembalm Sunlight = []-disembalm (ReturnZ x xs) = Return x : disembalm xs-disembalm (BindZ x d xs) = (x :>>= disembalm_go d) : disembalm xs+disembalm = disembalmBy [] (:)+{-# INLINE disembalm #-} +-- | Decompose a zombie as a list of possibilitie and fold the list.+disembalmBy :: r -> (MonadView t (Zombie t) a -> r -> r) -> Zombie t a -> r+disembalmBy e r = go where+ go Sunlight = e+ go (ReturnZ x xs) = Return x `r` go xs+ go (BindZ x c xs) = (x :>>= disembalm_go c) `r` go xs+{-# INLINE disembalmBy #-}+ disembalm_go :: Cat (Kleisli (Zombie t)) a b -> a -> Zombie t b-disembalm_go c a = viewL c (\(Kleisli k) -> k a) $ \(Kleisli k) c' -> disembalm_go2 (k a) c'+disembalm_go c a = viewL c (\k -> runKleisli k a) $+ \k d -> disembalm_go2 d $ runKleisli k a -disembalm_go2 :: Zombie t a -> Cat (Kleisli (Zombie t)) a b -> Zombie t b-disembalm_go2 x c = case x of- Sunlight -> Sunlight- ReturnZ a xs -> disembalm_go c a <|> disembalm_go2 xs c- BindZ t c' xs -> BindZ t (Tree c' c) $ disembalm_go2 xs c+disembalm_go2 :: Cat (Kleisli (Zombie t)) a b -> Zombie t a -> Zombie t b+disembalm_go2 c = go where+ go Sunlight = Sunlight+ go (ReturnZ a xs) = disembalm_go c a <|> go xs+ go (BindZ t d xs) = BindZ t (Tree d c) $ go xs -- | Like 'hoistSkeleton' hoistZombie :: forall s t a. (forall x. s x -> t x) -> Zombie s a -> Zombie t a