non-empty-zipper (empty) → 0.1.0.0
raw patch · 31 files changed
+469/−0 lines, 31 filesdep +QuickCheckdep +basedep +checkerssetup-changedbinary-added
Dependencies added: QuickCheck, base, checkers, lens, non-empty-zipper
Files
- ChangeLog.md +5/−0
- Data/List/NonEmptyZipper.hs +145/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- Spec.hs +44/−0
- default.nix +27/−0
- dist/build/Data/List/NonEmptyZipper.dyn_hi binary
- dist/build/Data/List/NonEmptyZipper.dyn_o binary
- dist/build/Data/List/NonEmptyZipper.hi binary
- dist/build/Data/List/NonEmptyZipper.o binary
- dist/build/autogen/Paths_non_empty_zipper.hs +50/−0
- dist/build/autogen/cabal_macros.h +97/−0
- dist/build/libHSnon-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM-ghc8.0.1.so binary
- dist/build/libHSnon-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM.a binary
- dist/build/spec/spec binary
- dist/build/spec/spec-tmp/Data/List/NonEmptyZipper.dyn_hi binary
- dist/build/spec/spec-tmp/Data/List/NonEmptyZipper.dyn_o binary
- dist/build/spec/spec-tmp/Data/List/NonEmptyZipper.hi binary
- dist/build/spec/spec-tmp/Data/List/NonEmptyZipper.o binary
- dist/build/spec/spec-tmp/Main.dyn_hi binary
- dist/build/spec/spec-tmp/Main.dyn_o binary
- dist/build/spec/spec-tmp/Main.hi binary
- dist/build/spec/spec-tmp/Main.o binary
- dist/package.conf.inplace/non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM.conf +28/−0
- dist/package.conf.inplace/package.cache binary
- dist/setup-config binary
- dist/setup-config.ghc-mod.cabal-components binary
- dist/setup-config.ghc-mod.package-db-stack binary
- dist/setup-config.ghc-mod.package-options binary
- dist/setup-config.ghc-mod.resolved-components binary
- non-empty-zipper.cabal +41/−0
@@ -0,0 +1,5 @@+# Revision history for NonEmptyZipper++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
@@ -0,0 +1,145 @@+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}++-----------------------------------------------------------------------------+-- |+-- Module : Data.List.NonEmptyZipper+-- Copyright : (C) 2017 Isaac Shapira+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Isaac Shapira <fresheyeball@gmail.com>+-- Stability : provisional+-- Portability : portable+--+-- Its the Zipper for NonEmpty lists.+--+----------------------------------------------------------------------------++module Data.List.NonEmptyZipper where++import Control.Lens+import Data.List.NonEmpty (NonEmpty (..))+import Data.Semigroup++data NonEmptyZipper a = NonEmptyZipper+ { _before :: ![a]+ , _current :: !a+ , _after :: ![a] }+ deriving (Show, Eq, Ord)++makeLenses ''NonEmptyZipper++instance Functor NonEmptyZipper where+ fmap f (NonEmptyZipper xs y zs) =+ NonEmptyZipper (f <$> xs) (f y) (f <$> zs)++instance Applicative NonEmptyZipper where+ pure x = NonEmptyZipper [x] x [x]+ NonEmptyZipper fxs fy fzs <*> NonEmptyZipper xs y zs =+ NonEmptyZipper (fxs <*> xs) (fy y) (fzs <*> zs)++{-|+Advance the current element forward by one.+If the current is the last element in the list, we do nothing.+-}+next :: NonEmptyZipper a -> NonEmptyZipper a+next (NonEmptyZipper xs y (z:zs)) =+ NonEmptyZipper (xs <> [y]) z zs+next z = z++-- | Advance the current element forward by one.+-- If the current is the last element in the list, we loop back to the first.+nextMod :: NonEmptyZipper a -> NonEmptyZipper a+nextMod (NonEmptyZipper (x:xs) y []) =+ NonEmptyZipper [] x (xs <> [y])+nextMod z = next z++-- | Move the current element backward by one.+-- If the current is the first element in the list, we do nothing.+previous :: NonEmptyZipper a -> NonEmptyZipper a+previous (NonEmptyZipper xs y zs) | not (null xs) =+ NonEmptyZipper (Prelude.init xs) (Prelude.last xs) (y:zs)+previous z = z++-- | Move the current element backward by one.+-- If the current is the first element in the list, we loop to the last element.+previousMod :: NonEmptyZipper a -> NonEmptyZipper a+previousMod (NonEmptyZipper [] y zs) | not (null zs) =+ NonEmptyZipper (y:Prelude.init zs) (Prelude.last zs) []+previousMod z = previous z++-- | Convert to a standard list. Current element information will be lost.+toList :: NonEmptyZipper a -> [a]+toList (NonEmptyZipper xs y zs) = xs <> (y:zs)++-- | Convert from @NonEmpty@. The first element will be the current element.+fromNonEmpty :: NonEmpty a -> NonEmptyZipper a+fromNonEmpty (x :| xs) = NonEmptyZipper [] x xs++-- | Is the current selection the first item in the collection?+inTheBeginning :: NonEmptyZipper a -> Bool+inTheBeginning (NonEmptyZipper [] _ _) = True+inTheBeginning _ = False++-- | Is the current selection the last item in the collection?+inTheEnd :: NonEmptyZipper a -> Bool+inTheEnd (NonEmptyZipper _ _ []) = True+inTheEnd _ = False++-- | Get the index of the current element in the collection.+getPosition :: NonEmptyZipper a -> Int+getPosition (NonEmptyZipper xs _ _) = Prelude.length xs++-- | Measure the size of the collection. Will be atleast 1.+length :: NonEmptyZipper a -> Int+length (NonEmptyZipper xs _ zs) = Prelude.length xs + 1 + Prelude.length zs++instance Semigroup (NonEmptyZipper a) where+ NonEmptyZipper xs y zs <> z =+ NonEmptyZipper xs y $ zs <> toList z++-- | Get the first element out of the NonEmptyZipper.+head :: NonEmptyZipper a -> a+head = \case+ NonEmptyZipper [] x _ -> x+ NonEmptyZipper (x:_) _ _ -> x++-- | Get all elements out of the NonEmptyZipper that are not the last element.+-- If there is only one element in the collection, it's @Nothing@.+init :: NonEmptyZipper a -> Maybe (NonEmptyZipper a)+init = \case+ NonEmptyZipper [] _ [] -> Nothing+ NonEmptyZipper xs _ [] ->+ Just $ NonEmptyZipper (Prelude.init xs) (Prelude.last xs) []+ NonEmptyZipper xs y zs ->+ Just $ NonEmptyZipper xs y (Prelude.init zs)++-- | Get the last element out of the NonEmptyZipper.+last :: NonEmptyZipper a -> a+last = \case+ NonEmptyZipper _ x [] -> x+ NonEmptyZipper _ _ xs -> Prelude.last xs++-- | Get all elements out of the NonEmptyZipper that are not the first element.+-- If there is only one element in the collection, its @Nothing@.+tail :: NonEmptyZipper a -> Maybe (NonEmptyZipper a)+tail = \case+ NonEmptyZipper [] _ [] -> Nothing+ NonEmptyZipper (_:xs) y zs -> Just $ NonEmptyZipper xs y zs+ NonEmptyZipper _ _ (z:zs) -> Just $ NonEmptyZipper [] z zs++-- | Flip the NonEmptyZipper, maintaining the current element.+reverse :: NonEmptyZipper a -> NonEmptyZipper a+reverse (NonEmptyZipper xs y zs) =+ NonEmptyZipper (Prelude.reverse zs) y (Prelude.reverse xs)++-- | Add one element to the front of a NonEmptyZipper.+cons :: a -> NonEmptyZipper a -> NonEmptyZipper a+cons x (NonEmptyZipper xs y zs) = NonEmptyZipper (x:xs) y zs++-- | This is like @pure@ but more intuitive.+-- The Applicative instance for @NonEmptyZipper@ is likely not what you expect.+wrap :: a -> NonEmptyZipper a+wrap x = NonEmptyZipper [] x []
@@ -0,0 +1,30 @@+Copyright (c) 2017, Isaac Shapira++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 Isaac Shapira 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.
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
@@ -0,0 +1,44 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Main where++import Control.Applicative+import Data.List.NonEmptyZipper+import Data.Monoid ()+import Data.Semigroup+import Prelude hiding (head, init, last, reverse,+ tail)+import Test.QuickCheck+import Test.QuickCheck.Checkers+import Test.QuickCheck.Classes++instance Arbitrary a => Arbitrary (NonEmptyZipper a) where+ arbitrary = liftA3 NonEmptyZipper arbitrary arbitrary arbitrary++instance Eq a => EqProp (NonEmptyZipper a) where+ (=-=) = eq++yo :: TestBatch -> IO ()+yo = checkBatch $ stdArgs { maxSuccess = 100, maxSize = 30 }++instance {-# OVERLAPS #-} Monoid (Maybe (NonEmptyZipper a)) where+ mempty = Nothing+ mappend (Just x) (Just y) = Just $ x <> y+ mappend Nothing x = x+ mappend x Nothing = x++main :: IO ()+main = do+ yo $ functor (NonEmptyZipper [] (0::Int, "", False) [])+ yo $ applicative (NonEmptyZipper [] (0::Int, "", False) [])+ yo $ monoid (Just $ NonEmptyZipper [] (0::Int, "", 0::Int) [])+ quickCheck $ \(x :: NonEmptyZipper Int) ->+ nextMod (previousMod x) == x && x == previousMod (nextMod x)+ quickCheck $ \(x :: NonEmptyZipper Int) ->+ reverse (reverse x) == x+ quickCheck $ \(x :: NonEmptyZipper Int) ->+ head (reverse x) == last x && head x == last (reverse x)+ quickCheck $ \(x :: NonEmptyZipper Int) ->+ fmap reverse (tail (reverse x)) == init x &&+ tail x == fmap reverse (init (reverse x))
@@ -0,0 +1,27 @@+{ nixpkgs ? import <nixpkgs> {}, compiler ? "default" }:++let++ inherit (nixpkgs) pkgs;++ f = { mkDerivation, base, checkers, comonad, lens, QuickCheck+ , stdenv+ }:+ mkDerivation {+ pname = "non-empty-zipper";+ version = "0.1.0.0";+ src = ./.;+ libraryHaskellDepends = [ base comonad lens ];+ testHaskellDepends = [ base checkers comonad lens QuickCheck ];+ license = stdenv.lib.licenses.bsd3;+ };++ haskellPackages = if compiler == "default"+ then pkgs.haskellPackages+ else pkgs.haskell.packages.${compiler};++ drv = haskellPackages.callPackage f {};++in++ if pkgs.lib.inNixShell then drv.env else drv
binary file changed (absent → 38090 bytes)
binary file changed (absent → 83584 bytes)
binary file changed (absent → 38078 bytes)
binary file changed (absent → 87408 bytes)
@@ -0,0 +1,50 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}+{-# OPTIONS_GHC -fno-warn-implicit-prelude #-}+module Paths_non_empty_zipper (+ version,+ getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,+ getDataFileName, getSysconfDir+ ) where++import qualified Control.Exception as Exception+import Data.Version (Version(..))+import System.Environment (getEnv)+import Prelude++#if defined(VERSION_base)++#if MIN_VERSION_base(4,0,0)+catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a+#else+catchIO :: IO a -> (Exception.Exception -> IO a) -> IO a+#endif++#else+catchIO :: IO a -> (Exception.IOException -> IO a) -> IO a+#endif+catchIO = Exception.catch++version :: Version+version = Version [0,1,0,0] []+bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath++bindir = "/home/isaac/.cabal/bin"+libdir = "/home/isaac/.cabal/lib/x86_64-linux-ghc-8.0.1/non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM"+dynlibdir = "/home/isaac/.cabal/lib/x86_64-linux-ghc-8.0.1"+datadir = "/home/isaac/.cabal/share/x86_64-linux-ghc-8.0.1/non-empty-zipper-0.1.0.0"+libexecdir = "/home/isaac/.cabal/libexec"+sysconfdir = "/home/isaac/.cabal/etc"++getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath+getBinDir = catchIO (getEnv "non_empty_zipper_bindir") (\_ -> return bindir)+getLibDir = catchIO (getEnv "non_empty_zipper_libdir") (\_ -> return libdir)+getDynLibDir = catchIO (getEnv "non_empty_zipper_dynlibdir") (\_ -> return dynlibdir)+getDataDir = catchIO (getEnv "non_empty_zipper_datadir") (\_ -> return datadir)+getLibexecDir = catchIO (getEnv "non_empty_zipper_libexecdir") (\_ -> return libexecdir)+getSysconfDir = catchIO (getEnv "non_empty_zipper_sysconfdir") (\_ -> return sysconfdir)++getDataFileName :: FilePath -> IO FilePath+getDataFileName name = do+ dir <- getDataDir+ return (dir ++ "/" ++ name)
@@ -0,0 +1,97 @@+/* DO NOT EDIT: This file is automatically generated by Cabal */++/* package non-empty-zipper-0.1.0.0 */+#define VERSION_non_empty_zipper "0.1.0.0"+#define MIN_VERSION_non_empty_zipper(major1,major2,minor) (\+ (major1) < 0 || \+ (major1) == 0 && (major2) < 1 || \+ (major1) == 0 && (major2) == 1 && (minor) <= 0)++/* package base-4.9.0.0 */+#define VERSION_base "4.9.0.0"+#define MIN_VERSION_base(major1,major2,minor) (\+ (major1) < 4 || \+ (major1) == 4 && (major2) < 9 || \+ (major1) == 4 && (major2) == 9 && (minor) <= 0)++/* package lens-4.14 */+#define VERSION_lens "4.14"+#define MIN_VERSION_lens(major1,major2,minor) (\+ (major1) < 4 || \+ (major1) == 4 && (major2) < 14 || \+ (major1) == 4 && (major2) == 14 && (minor) <= 0)++/* tool alex-3.1.0 */+#define TOOL_VERSION_alex "3.1.0"+#define MIN_TOOL_VERSION_alex(major1,major2,minor) (\+ (major1) < 3 || \+ (major1) == 3 && (major2) < 1 || \+ (major1) == 3 && (major2) == 1 && (minor) <= 0)++/* tool gcc-5.4.0 */+#define TOOL_VERSION_gcc "5.4.0"+#define MIN_TOOL_VERSION_gcc(major1,major2,minor) (\+ (major1) < 5 || \+ (major1) == 5 && (major2) < 4 || \+ (major1) == 5 && (major2) == 4 && (minor) <= 0)++/* tool ghc-8.0.1 */+#define TOOL_VERSION_ghc "8.0.1"+#define MIN_TOOL_VERSION_ghc(major1,major2,minor) (\+ (major1) < 8 || \+ (major1) == 8 && (major2) < 0 || \+ (major1) == 8 && (major2) == 0 && (minor) <= 1)++/* tool ghc-pkg-8.0.1 */+#define TOOL_VERSION_ghc_pkg "8.0.1"+#define MIN_TOOL_VERSION_ghc_pkg(major1,major2,minor) (\+ (major1) < 8 || \+ (major1) == 8 && (major2) < 0 || \+ (major1) == 8 && (major2) == 0 && (minor) <= 1)++/* tool haddock-2.17.2 */+#define TOOL_VERSION_haddock "2.17.2"+#define MIN_TOOL_VERSION_haddock(major1,major2,minor) (\+ (major1) < 2 || \+ (major1) == 2 && (major2) < 17 || \+ (major1) == 2 && (major2) == 17 && (minor) <= 2)++/* tool happy-1.19.0 */+#define TOOL_VERSION_happy "1.19.0"+#define MIN_TOOL_VERSION_happy(major1,major2,minor) (\+ (major1) < 1 || \+ (major1) == 1 && (major2) < 19 || \+ (major1) == 1 && (major2) == 19 && (minor) <= 0)++/* tool hpc-0.67 */+#define TOOL_VERSION_hpc "0.67"+#define MIN_TOOL_VERSION_hpc(major1,major2,minor) (\+ (major1) < 0 || \+ (major1) == 0 && (major2) < 67 || \+ (major1) == 0 && (major2) == 67 && (minor) <= 0)++/* tool hsc2hs-0.68 */+#define TOOL_VERSION_hsc2hs "0.68"+#define MIN_TOOL_VERSION_hsc2hs(major1,major2,minor) (\+ (major1) < 0 || \+ (major1) == 0 && (major2) < 68 || \+ (major1) == 0 && (major2) == 68 && (minor) <= 0)++/* tool pkg-config-0.26 */+#define TOOL_VERSION_pkg_config "0.26"+#define MIN_TOOL_VERSION_pkg_config(major1,major2,minor) (\+ (major1) < 0 || \+ (major1) == 0 && (major2) < 26 || \+ (major1) == 0 && (major2) == 26 && (minor) <= 0)++/* tool strip-2.27 */+#define TOOL_VERSION_strip "2.27"+#define MIN_TOOL_VERSION_strip(major1,major2,minor) (\+ (major1) < 2 || \+ (major1) == 2 && (major2) < 27 || \+ (major1) == 2 && (major2) == 27 && (minor) <= 0)++#define CURRENT_COMPONENT_ID "non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM"++#define CURRENT_PACKAGE_KEY "non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM"+
binary file changed (absent → 114536 bytes)
binary file changed (absent → 105890 bytes)
binary file changed (absent → 1659248 bytes)
binary file changed (absent → 38000 bytes)
binary file changed (absent → 74448 bytes)
binary file changed (absent → 37988 bytes)
binary file changed (absent → 78272 bytes)
binary file changed (absent → 48772 bytes)
binary file changed (absent → 119664 bytes)
binary file changed (absent → 48760 bytes)
binary file changed (absent → 125160 bytes)
@@ -0,0 +1,28 @@+name: non-empty-zipper+version: 0.1.0.0+id: non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM+key: non-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM+license: BSD3+maintainer: fresheyeball@gmail.com+synopsis: The Zipper for NonEmpty+description:+ The Zipper for NonEmpty. Useful for things like tabs,+ button groups, and slideshows. Basically any case in which+ you want to ensure you have one selected value from a+ list of values.+category: Data+author: Isaac Shapira+exposed: True+exposed-modules:+ Data.List.NonEmptyZipper+abi: +trusted: False+import-dirs: /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0/dist/build+library-dirs: /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0/dist/build+ /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0/dist/build+data-dir: /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0+hs-libraries: HSnon-empty-zipper-0.1.0.0-AA3uqRxiCyIKe6pjfbiVUM+depends:+ base-4.9.0.0 lens-4.14-7r1pEZqaiiGcgCHqBkPQE+haddock-interfaces: /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0/dist/doc/html/non-empty-zipper/non-empty-zipper.haddock+haddock-html: /home/isaac/Projects/NonEmptyZipper/non-empty-zipper-0.1.0.0/dist/doc/html/non-empty-zipper
binary file changed (absent → 2283 bytes)
binary file changed (absent → 275180 bytes)
binary file changed (absent → 1430 bytes)
binary file changed (absent → 383 bytes)
binary file changed (absent → 1001 bytes)
binary file changed (absent → 3180 bytes)
@@ -0,0 +1,41 @@+-- Initial NonEmptyZipper.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++name: non-empty-zipper+version: 0.1.0.0+synopsis: The Zipper for NonEmpty+description: The Zipper for NonEmpty. Useful for things like tabs,+ button groups, and slideshows. Basically any case in which+ you want to ensure you have one selected value from a+ list of values.+license: BSD3+license-file: LICENSE+author: Isaac Shapira+maintainer: fresheyeball@gmail.com+-- copyright:+category: Data+build-type: Simple+extra-source-files: ChangeLog.md+ , Data.List.NonEmptyZipper.hs+cabal-version: >=1.10++library+ exposed-modules: Data.List.NonEmptyZipper+ -- other-modules:+ -- other-extensions:+ build-depends: base >=4.9 && <4.10+ , lens+ -- hs-source-dirs:+ default-language: Haskell2010++test-suite spec+ type: exitcode-stdio-1.0+ -- hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , lens+ , non-empty-zipper+ , QuickCheck+ , checkers+ ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010