zippers 0.2 → 0.2.1
raw patch · 6 files changed
+178/−20 lines, 6 filesdep +criteriondep +zippersdep ~basedep ~lensnew-uploader
Dependencies added: criterion, zippers
Dependency ranges changed: base, lens
Files
- .travis.yml +100/−9
- CHANGELOG.markdown +4/−0
- README.markdown +1/−1
- benchmarks/zipper.hs +46/−0
- src/Control/Zipper/Internal.hs +12/−5
- zippers.cabal +15/−5
.travis.yml view
@@ -1,16 +1,108 @@-language: haskell+# 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.4.2+ compiler: ": #GHC 7.4.2"+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.4.2,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.18 GHCVER=7.6.3+ compiler: ": #GHC 7.6.3"+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.6.3,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.18 GHCVER=7.8.4+ compiler: ": #GHC 7.8.4"+ addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,hlint], 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,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=8.0.1+ compiler: ": #GHC 8.0.1"+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,hlint], sources: [hvr-ghc]}}+ - env: CABALVER=1.24 GHCVER=head+ compiler: ": #GHC head"+ addons: {apt: {packages: [cabal-install-1.24,ghc-head,hlint], sources: [hvr-ghc]}}++ allow_failures:+ - env: CABALVER=1.24 GHCVER=head+ before_install:- # Uncomment whenever hackage is down.- # - mkdir -p ~/.cabal && cp travis/config ~/.cabal/config && cabal update- - travis/cabal-apt-install $mode+ - unset CC+ - export PATH=$HOME/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH install:- - cabal configure $mode- - cabal build+ - 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 --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 installplan.txt $HOME/.cabsnap/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 -j --only-dependencies --enable-tests;+ if [ "$GHCVER" = "7.10.3" ]; then cabal install Cabal-1.22.4.0; fi;+ 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:- - $script && hlint src --cpp-define HLINT+ # -v2 provides useful information for debugging+ - cabal configure --enable-tests -v2 + # this builds all libraries and executables+ # (including tests/benchmarks)+ - cabal build++ - cabal test+ - hlint src --cpp-define HLINT++ # 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+ notifications: irc: channels:@@ -19,5 +111,4 @@ template: - "\x0313zippers\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}" -env:- - mode="--enable-tests" script="cabal test"+# EOF
CHANGELOG.markdown view
@@ -1,3 +1,7 @@+0.2.1+---+* Migrate zipper benchmarks from lens+ 0.1 --- * Repository initialized
README.markdown view
@@ -1,7 +1,7 @@ zippers === -[](http://travis-ci.org/ekmett/zippers)+[](https://hackage.haskell.org/package/zippers) [](http://travis-ci.org/ekmett/zippers) Zippers are a way of accessing and manipulating data deep within a structure. This library uses Lenses and Traversals from the lens library to do this effectively.
+ benchmarks/zipper.hs view
@@ -0,0 +1,46 @@+module Main+ ( main -- :: IO ()+ ) where++import Control.Lens+import Control.Zipper+import Criterion.Main++main :: IO ()+main = defaultMain+ [ bgroup "rezip"+ [ bench "rezip" $ nf tugAndRezip1 ['a'..'z']+ , bench "farthest leftward" $ nf tugAndRezip2 ['a'..'z']+ , bench "leftmost" $ nf tugAndRezip3 ['a'..'z']+ , bench "tugTo" $ nf tugAndRezip4 ['a'..'z']+ ]+ , bgroup "zipper creation"+ [ bench "over traverse id" $ nf (over traverse id) ['a'..'z']+ , bench "zipper" $ nf zipTraverseRezip ['a'..'z']+ ]+ , bgroup "downward"+ [ bench "downward _1" $ nf downwardAndRezip1 (['a'..'z'],['z'..'a'])+ , bench "fromWithin" $ nf downwardAndRezip2 (['a'..'z'],['z'..'a'])+ ]+ ]++-- What's the fastest rezip of all?+tugAndRezip1, tugAndRezip2, tugAndRezip3 :: String -> String+tugAndRezip1 xs = zipntugs 25 xs & focus .~ 'a' & rezip+tugAndRezip2 xs = zipntugs 25 xs & focus .~ 'b' & farthest leftward & rezip+tugAndRezip3 xs = zipntugs 25 xs & focus .~ 'c' & leftmost & rezip+tugAndRezip4 xs = zipntugs 25 xs & focus .~ 'd' & tugTo 0 & rezip++zipntugs i x = zipper x & fromWithin traverse & tugs rightward i++-- How fast is creating and destroying a zipper compared to+-- a regular traversal?+zipTraverseRezip x = zipper x & fromWithin traverse & rezip++-- is 'downward' any faster than the composition of traverse?+downwardAndRezip1 :: (String, String) -> (String, String)+downwardAndRezip1 xs =+ zipper xs & downward _1 & fromWithin traverse & focus .~ 'h' & rezip+downwardAndRezip2 :: (String, String) -> (String, String)+downwardAndRezip2 xs =+ zipper xs & fromWithin (_1.traverse) & focus .~ 'g' & rezip
src/Control/Zipper/Internal.hs view
@@ -15,6 +15,10 @@ {-# LANGUAGE Trustworthy #-} #endif +#ifndef MIN_VERSION_base+#define MIN_VERSION_base(x,y,z) 1+#endif+ ----------------------------------------------------------------------------- -- | -- Module : Control.Zipper.Internal@@ -42,12 +46,15 @@ import Control.Lens.Setter import Control.Lens.Traversal import Control.Lens.Type-import Data.Foldable import Data.Functor.Apply import Data.Maybe import Data.Monoid import Data.Profunctor.Unsafe +#if !(MIN_VERSION_base(4,8,0))+import Data.Foldable+#endif+ -- $setup -- >>> :set -XNoOverloadedStrings -- >>> import Control.Lens@@ -406,7 +413,7 @@ -- | Jerk the 'Zipper' one 'tooth' to the 'rightward' within the current 'Lens' or 'Traversal'. -- -- Attempts to move past the start of the current 'Traversal' (or trivially, the current 'Lens')--- will return 'Nothing'.+-- will return 'mzero'. -- -- >>> isNothing $ zipper "hello" & rightward -- True@@ -420,13 +427,13 @@ -- >>> rezip $ zipper (1,2) & fromWithin both & tug rightward & focus .~ 3 -- (1,3) rightward :: MonadPlus m => h :> a:@i -> m (h :> a:@i)-rightward (Zipper h t o p i a) = mover p (Leaf i a) mzero $ \q j b -> return $ Zipper h t (o + 1) q j b where+rightward (Zipper h t o p i a) = mover p (Leaf i a) mzero $ \q j b -> return $ Zipper h t (o + 1) q j b {-# INLINE rightward #-} -- | Jerk the 'Zipper' 'leftward' one 'tooth' within the current 'Lens' or 'Traversal'. -- -- Attempts to move past the end of the current 'Traversal' (or trivially, the current 'Lens')--- will return 'Nothing'.+-- will return 'mzero'. -- -- >>> isNothing $ zipper "hello" & leftward -- True@@ -560,7 +567,7 @@ -- | Move the 'Zipper' horizontally to the element in the @n@th position in the -- current level, absolutely indexed, starting with the 'farthest' 'leftward' as @0@. ----- This returns 'Nothing' if the target element doesn't exist.+-- This returns 'mzero' if the target element doesn't exist. -- -- @'jerkTo' n ≡ 'jerks' 'rightward' n '.' 'farthest' 'leftward'@ --
zippers.cabal view
@@ -1,6 +1,6 @@ name: zippers category: zippers-version: 0.2+version: 0.2.1 license: BSD3 cabal-version: >= 1.10 license-file: LICENSE@@ -36,8 +36,8 @@ build-depends: base >= 4.4 && < 5, lens >= 4 && < 5,- profunctors >= 4 && < 5,- semigroupoids >= 4 && < 5+ profunctors >= 4 && < 6,+ semigroupoids >= 4 && < 6 exposed-modules: Control.Zipper Control.Zipper.Internal@@ -52,6 +52,16 @@ doctest >= 0.9.1, filepath ghc-options: -Wall -threaded- if impl(ghc<7.6.1)- ghc-options: -Werror hs-source-dirs: tests++benchmark zipper+ type: exitcode-stdio-1.0+ main-is: zipper.hs+ default-language: Haskell2010+ ghc-options: -O2 -threaded -fdicts-cheap -funbox-strict-fields+ hs-source-dirs: benchmarks+ build-depends:+ base,+ criterion,+ lens,+ zippers