packages feed

separated 0.1.2 → 0.2.0

raw patch · 7 files changed

+885/−497 lines, 7 filesdep −papadep ~basenew-uploader

Dependencies removed: papa

Dependency ranges changed: base

Files

+ LICENCE view
@@ -0,0 +1,31 @@+Copyright (c) 2017, Commonwealth Scientific and Industrial Research Organisation+(CSIRO) ABN 41 687 119 230.++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 QFPL 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.
changelog view
@@ -1,3 +1,8 @@+0.2.0++* Refactoring with lots of changes to data types.+* Introduce nix for building.+ 0.1.2  * Add instance of `Wrapped` and `Swapped`.
− etc/LICENCE
@@ -1,27 +0,0 @@-Copyright 2013-2014 Tony Morris--All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions-are met:-1. Redistributions of source code must retain the above copyright-   notice, this list of conditions and the following disclaimer.-2. 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.-3. Neither the name of the author nor the names of his contributors-   may be used to endorse or promote products derived from this software-   without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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.
separated.cabal view
@@ -1,13 +1,16 @@ name:               separated-version:            0.1.2+version:            0.2.0 license:            BSD3-license-File:       etc/LICENCE+license-File:       LICENCE author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> maintainer:         Tony Morris copyright:          Copyright (c) 2016, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230. synopsis:           A data type with elements separated by values category:           Data-description:        A data type with elements separated by values+description:       +  <<http://i.imgur.com/0h9dFhl.png>>+  .+   A data type with elements separated by values homepage:           https://github.com/data61/separated bug-reports:        https://github.com/data61/separated/issues cabal-version:      >= 1.10@@ -31,7 +34,6 @@                     , semigroups >= 0.9                     , semigroupoids >= 4.0                     , bifunctors >= 4.0-                    , papa                        ghc-options:                     -Wall@@ -44,8 +46,6 @@    exposed-modules:                     Data.Separated-                    Data.Separated.Separated-                    Data.Separated.SeparatedCons  test-suite doctests   type:
src/Data/Separated.hs view
@@ -1,8 +1,848 @@ {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE RankNTypes #-}  module Data.Separated(-  module S+-- * Data types+  Separated(..)+, Separated1(..)+, Pesarated(..)+, Pesarated1(..)+-- * Iso+, separated+, separated1+, pesarated+, pesarated1+-- * Viewing+, HasHead(..)+, HasTail(..)+-- * Constructing+, Separated1Single(..)+, Pesarated1Single(..)+, Construct(..)+, SeparatedCons(..)+, PesaratedCons(..)+-- * Appending+, Appends(..)+-- * Alternating+, separatedBy+, separatedBy1+, pesaratedBy+, pesaratedBy1 ) where -import Data.Separated.Separated as S-import Data.Separated.SeparatedCons as S+import Control.Applicative(Applicative((<*>), pure), Alternative(many))+import Control.Category(Category((.), id))+import Control.Lens(Swapped(swapped), Iso, Lens, iso, from, (#), (^.), _1, _2, makeWrapped, _Wrapped)+import Data.Bifoldable(Bifoldable(bifoldr))+import Data.Bifunctor(Bifunctor(bimap), first)+import Data.Bitraversable(Bitraversable(bitraverse))+import Data.Eq(Eq)+import Data.Foldable(foldr)+import Data.Functor(Functor(fmap), (<$>))+import Data.Functor.Apply as Apply(Apply((<.>)))+import Data.List(intercalate, zipWith, repeat)+import Data.Monoid(Monoid(mappend, mempty))+import Data.Ord(Ord)+import Data.Semigroup as Semigroup(Semigroup((<>)))+import Data.String(String)+import Data.Traversable(traverse)+import Data.Tuple(uncurry)+import Prelude(Show(show))++-- $setup+-- >>> :set -XNoImplicitPrelude+-- >>> :set -XFlexibleContexts+-- >>> import Control.Lens(set)+-- >>> import Control.Monad(return)+-- >>> import Data.Char(toUpper)+-- >>> import Data.Either(isLeft)+-- >>> import Prelude hiding (id, (.))+-- >>> import Text.Parsec(parse, char, digit)+-- >>> import Test.QuickCheck(Arbitrary(..))+-- >>> instance (Arbitrary s, Arbitrary a) => Arbitrary (Separated s a) where arbitrary = fmap (^. separated) arbitrary+-- >>> instance (Arbitrary a, Arbitrary s) => Arbitrary (Separated1 s a) where arbitrary = do a <- arbitrary; x <- arbitrary; return ((a, x) ^. separated1)+-- >>> instance (Arbitrary s, Arbitrary a) => Arbitrary (Pesarated s a) where arbitrary = fmap (^. pesarated) arbitrary+-- >>> instance (Arbitrary s, Arbitrary a) => Arbitrary (Pesarated1 s a) where arbitrary = fmap (^. pesarated1) arbitrary+-- >>> let emptySeparated :: Separated s a; emptySeparated = empty+-- >>> let emptyPesarated :: Pesarated s a; emptyPesarated = empty++-- | A list of pairs of separator and value. Separated by @a@ in values @b@.+-- There are an even number of separators as there are values.+newtype Separated a b =+  Separated [(a, b)]+  deriving (Eq, Ord)++-- | A list of pairs of separator and value. Separated by @a@ in values @b@.+-- There is one more value than there are separators.+data Separated1 b a =+  Separated1 b (Separated a b)+  deriving (Eq, Ord)++-- | The @Separated@ type constructor, flipped.+newtype Pesarated b a =+  Pesarated (Separated a b)+  deriving (Eq, Ord)++-- | The @Separated1@ type constructor, flipped.+newtype Pesarated1 a b =+  Pesarated1 (Separated1 b a)+  deriving (Eq, Ord)++-- | The isomorphism to a list of pairs of element and separator values.+--+-- >>> separated # emptySeparated+-- []+--+-- >>> separated # ('x' +: 6 +: emptySeparated)+-- [('x',6)]+--+-- >>> [] ^. separated+-- []+--+-- >>> [(6, [])] ^. separated+-- [6,[]]+separated ::+  Iso [(a, b)] [(c, d)] (Separated a b) (Separated c d)+separated =+  from _Wrapped++-- | The isomorphism to element values interspersed with a separator.+--+-- >>> separated1 # (singleSeparated 6)+-- (6,[])+--+-- >>> separated1 # (5 +: 'x' +: singleSeparated 6)+-- (5,['x',6])+--+-- >>> (6, emptySeparated) ^. separated1+-- [6]+--+-- >>> (5, 'x' +- 6) ^. separated1+-- [5,'x',6]+separated1 ::+  Iso (a, Separated s a) (b, Separated t b) (Separated1 a s) (Separated1 b t)+separated1 =+  iso (uncurry Separated1) (\(Separated1 a x) -> (a, x))++-- | The isomorphism to element values interspersed with a separator.+--+-- >>> pesarated # emptyPesarated+-- []+--+-- >>> ('a', 'x' +- 6) ^. pesarated1+-- ['a',6,'x']+--+-- >>> ('x' -: 6 -: emptyPesarated)+-- ['x',6]+pesarated ::+  Iso [(a, b)] [(c, d)] (Pesarated b a) (Pesarated d c)+pesarated =+  separated . from _Wrapped++-- | The isomorphism to element values interspersed with a separator.+--+-- >>> pesarated1 # singlePesarated 6+-- (6,[])+--+-- >>> pesarated1 # (8 -: 'x' -: singlePesarated 6)+-- (8,['x',6])+--+-- >>> (6, empty) ^. pesarated1+-- [6]+--+-- >>> (5, 'x' -+ 6) ^. pesarated1+-- [5,'x',6]+pesarated1 ::+  Iso (a, Pesarated a s) (b, Pesarated b t) (Pesarated1 s a) (Pesarated1 t b)+pesarated1 =+  iso+    (\(a, Pesarated x) -> Pesarated1 (Separated1 a x))+    (\(Pesarated1 (Separated1 a x)) -> (a, Pesarated x))++-- | Structures that have a head element.+class HasHead s t a b | s -> a, t -> b, s b -> t, t a -> s where+  headL ::+    Lens s t a b++-- | A lens on the first element value.+--+-- >>> (singleSeparated 7 :: Separated1 Int Char) ^. headL+-- 7+--+-- prop> (singleSeparated x :: Separated1 Int Char) ^. headL == (x :: Int)+instance HasHead (Separated1 a t) (Separated1 a t) a a where+  headL =+    from separated1 . _1++-- | A lens on the first element value.+--+-- >>> (singlePesarated 7 :: Pesarated1 Char Int) ^. headL+-- 7+--+-- prop> (singlePesarated x :: Pesarated1 Char Int) ^. headL == (x :: Int)+instance HasHead (Pesarated1 a t) (Pesarated1 a t) t t where+  headL =+    _Wrapped . headL++-- | Structures that have a tail.+class HasTail s t a b | s -> a, t -> b, s b -> t, t a -> s where+  tailL ::+    Lens s t a b++-- | A lens on the tail.+--+-- prop> (d +: e +: (singleSeparated x :: Separated1 Int Char)) ^. tailL == e +: x +: emptySeparated+instance HasTail (Separated1 a s) (Separated1 a t) (Separated s a) (Separated t a) where+  tailL =+    from separated1 . _2++-- | A lens on the tail.+--+-- prop> (d -: e -: (singlePesarated x :: Pesarated1 Char Int)) ^. tailL == e -: x -: emptyPesarated+instance HasTail (Pesarated1 a s) (Pesarated1 b s) (Pesarated s a) (Pesarated s b) where+  tailL =+    _Wrapped . tailL . from _Wrapped++-- | Construct a single separated value.+class Separated1Single f where+  singleSeparated ::+    a+    -> f a s++-- | Zero element values interspersed with one element.+--+-- >>> (singleSeparated 4 :: Separated1 Int Char)+-- [4]+--+-- prop> (singleSeparated x  :: Separated1 Int Char) ^. tailL == emptySeparated+instance Separated1Single Separated1 where+  singleSeparated a =+    Separated1 a mempty++class Pesarated1Single f where+  singlePesarated ::+    a+    -> f s a++-- | Zero element values interspersed with one element.+--+-- >>>  (singlePesarated 4 :: Pesarated1 Char Int)+-- [4]+--+-- prop> (singlePesarated x  :: Pesarated1 Int Char) ^. tailL == emptyPesarated+instance Pesarated1Single Pesarated1 where+  singlePesarated a =+    Pesarated1 (Separated1 a mempty)++-- | Construction of separated values.+class Construct f where+  (+-) ::+    s+    -> a+    -> f s a+  (-+) ::+    s+    -> a+    -> f a s+  empty ::+    f s a+  sprinkle ::+    s+    -> [a]+    -> f s a++infixl 9 +-++-- | One element and one separator.+--+-- >>> (7 +- "abc") :: Separated Int String+-- [7,"abc"]+--+-- >>> 7 +: "abc" +: (8 +- "def") :: Separated Int String +-- [7,"abc",8,"def"]+instance Construct Separated where+  s +- a =+    Separated [(s, a)]+  s -+ a =+    swapped # (s +- a)+  empty =+    Separated mempty+  sprinkle s as =+    Separated+      ((,) s <$> as)++-- | One element and one separator.+--+-- >>> (7 -+ "abc") :: Pesarated String Int+-- [7,"abc"]+--+-- >>> 7 -: "abc" -: (8 -+ "def") :: Pesarated String Int+-- [7,"abc",8,"def"]+instance Construct Pesarated where+  s +- a =+    swapped . _Wrapped # (s +- a)+  s -+ a =+    _Wrapped # (s +- a)+  empty =+    Pesarated empty+  sprinkle s as =+    Pesarated+      (swapped # sprinkle s as)++-- | Prepend a value to a separated-like structure.+class (f ~ SeparatedConsF g, g ~ SeparatedConsG f) => SeparatedCons f g where+  type SeparatedConsF g :: * -> * -> *+  type SeparatedConsG f :: * -> * -> *+  (+:) ::+    a+    -> f b a+    -> g a b+  +infixr 5 +:++instance SeparatedCons Separated1 Separated where+  type SeparatedConsF Separated = Separated1+  type SeparatedConsG Separated1 = Separated+  s +: Separated1 a (Separated x) =+    Separated ((s, a) : x)++instance SeparatedCons Separated Separated1 where+  type SeparatedConsF Separated1 = Separated+  type SeparatedConsG Separated = Separated1+  (+:) =+    Separated1++-- | Prepend a value to a separated-like structure.+class (f ~ PesaratedConsF g, g ~ PesaratedConsG f) => PesaratedCons f g where+  type PesaratedConsF g :: * -> * -> *+  type PesaratedConsG f :: * -> * -> *+  (-:) ::+    b+    -> f b a+    -> g a b+  +infixr 5 -:++instance PesaratedCons Pesarated Pesarated1 where+  type PesaratedConsF Pesarated1 = Pesarated+  type PesaratedConsG Pesarated = Pesarated1+  b -: (Pesarated x) =+    Pesarated1+      (b +: x)++instance PesaratedCons Pesarated1 Pesarated where+  type PesaratedConsF Pesarated = Pesarated1+  type PesaratedConsG Pesarated1 = Pesarated+  b -: (Pesarated1 x) =+    Pesarated (b +: x)++-- | Append two to make one.+class Appends a b c | a b -> c where+  (<++>) ::+    a+    -> b+    -> c++infixr 5 <++>++-- | Append two lists of separated values to produce a list of pairs of separator and element values.+--+-- >>> (singleSeparated 7 :: Separated1 Int Char) <++> (singleSeparated 'a' :: Separated1 Char Int)+-- [7,'a']+--+-- 'a' +: (singleSeparated 7 :: Separated1 Int Char) <++> (singleSeparated 'b' :: Separated1 Char Int)+-- ['a',7,'b']+--+-- prop> a +: (b :: Separated Int Int) == a +: b --  (a +: (b <++> c)) == ((a +: b) <++> c)+instance Appends (Separated1 s a) (Separated1 a s) (Separated s a) where+  Separated1 s x <++> Separated1 t (Separated y) =+    let (q, r') = (s, x) ^. separated1 . shift+    in Separated (q <> ((r', t) : y))++-- | Append element values interspersed with a separator to a list of pairs of separator and element values.+--+-- >>> (emptySeparated :: Separated Int Char) <++> (singleSeparated 7 :: Separated1 Int Char)+-- [7]+--+-- >>> (emptySeparated :: Separated Int Char) <++> 6 +: 'x' +: (singleSeparated 7 :: Separated1 Int Char)+-- [6,'x',7]+--+-- >>> 'w' +: (emptySeparated :: Separated Int Char) <++> 6 +: 'x' +: (singleSeparated 7 :: Separated1 Int Char)+-- ['w',6,'x',7]+instance Appends (Separated s a) (Separated1 s a) (Separated1 s a) where+  Separated x <++> Separated1 t y =+    let (z, w') = separated1 . shift # (x, t)+    in Separated1 z (w' <> y)++-- | Append a list of pairs of separator and element values to element values interspersed with a separator.+--+-- >>> (singleSeparated 7 :: Separated1 Int Char) <++> (emptySeparated :: Separated Char Int)+-- [7]+--+-- >>> (singleSeparated 6 :: Separated1 Int Char) <++> 'x' +: 7 +: (emptySeparated :: Separated Char Int)+-- [6,'x',7]+--+-- >>> 'w' +: (singleSeparated 6 :: Separated1 Int Char) <++> 'x' +: 7 +: (emptySeparated :: Separated Char Int)+-- ['w',6,'x',7]+instance Appends (Separated1 a s) (Separated s a) (Separated1 a s) where+  Separated1 a x <++> y =+    Separated1 a (x <> y)++-- | Alternate separated values e.g. `f ~ Parser`.+--+-- >>> parse (separatedBy (char ',') digit) "test" ""+-- Right []+--+-- >>> isLeft (parse (separatedBy (char ',') digit) "test" ",")+-- True+--+-- >>> parse (separatedBy (char ',') digit) "test" ",1"+-- Right [',','1']+--+-- >>> isLeft (parse (separatedBy (char ',') digit) "test" ",1,")+-- True+--+-- >>> parse (separatedBy (char ',') digit) "test" ",1,2,3,4,5"+-- Right [',','1',',','2',',','3',',','4',',','5']+separatedBy ::+  Alternative f =>+  f a+  -> f b+  -> f (Separated a b)+separatedBy a b =+  Separated <$>+    many+      ((,) <$> a <*> b)++-- | Alternate separated values e.g. `f ~ Parser`.+--+-- >>> isLeft (parse (separatedBy1 (char ',') digit) "test" "")+-- True+--+-- >>> parse (separatedBy1 (char ',') digit) "test" ","+-- Right [',']+--+-- >>> isLeft (parse (separatedBy1 (char ',') digit) "test" ",1")+-- True+--+-- >>> parse (separatedBy1 (char ',') digit) "test" ",1,"+-- Right [',','1',',']+--+-- >>>  parse (separatedBy1 (char ',') digit) "test" ",1,2,3,4,5,"+-- Right [',','1',',','2',',','3',',','4',',','5',',']+separatedBy1 ::+  Alternative f =>+  f b+  -> f a+  -> f (Separated1 b a)+separatedBy1 b a =+  Separated1 <$> b <*> separatedBy a b++-- | Alternate separated values e.g. `f ~ Parser`.+--+-- >>> parse (pesaratedBy (char ',') digit) "test" ""+-- Right []+--+-- >>> isLeft (parse (pesaratedBy (char ',') digit) "test" ",")+-- True+--+-- >>> parse (separatedBy (char ',') digit) "test" ",1"+-- Right [',','1']+--+-- >>> isLeft (parse (pesaratedBy (char ',') digit) "test" ",1,")+-- True+--+-- >>> parse (pesaratedBy (char ',') digit) "test" ",1,2,3,4,5"+-- Right [',','1',',','2',',','3',',','4',',','5']+pesaratedBy ::+  Alternative f =>+  f a+  -> f b+  -> f (Pesarated b a)+pesaratedBy a b =+  Pesarated <$> separatedBy a b++-- | Alternate separated values e.g. `f ~ Parser`.+--+-- >>> isLeft (parse (pesaratedBy1 (char ',') digit) "test" "")+-- True+--+-- >>> parse (pesaratedBy1 (char ',') digit) "test" ","+-- Right [',']+--+-- >>> isLeft (parse (pesaratedBy1 (char ',') digit) "test" ",1")+-- True+--+-- >>> parse (pesaratedBy1 (char ',') digit) "test" ",1,"+-- Right [',','1',',']+--+-- >>>  parse (pesaratedBy1 (char ',') digit) "test" ",1,2,3,4,5,"+-- Right [',','1',',','2',',','3',',','4',',','5',',']+pesaratedBy1 ::+  Alternative f =>+  f b+  -> f a+  -> f (Pesarated1 a b)+pesaratedBy1 b a =+  Pesarated1 <$> separatedBy1 b a++-- | The isomorphism that swaps elements with their separators.+--+-- >>> swapped # emptySeparated+-- []+--+-- >>> swapped # ('x' +: 6 +: emptySeparated)+-- [6,'x']+--+-- >>> emptySeparated ^. swapped+-- []+--+-- >>> ('x' +: 6 +: emptySeparated) ^. swapped+-- [6,'x']+instance Swapped Separated where+  swapped =+    let swap = (\(Separated x) -> Separated (fmap (\(a, b) -> (b, a)) x))+    in iso swap swap++instance Bifunctor Separated where+  bimap f g (Separated x) =+    Separated (fmap (bimap f g) x)++instance Bifoldable Separated where+  bifoldr f g z (Separated x) =+    foldr (\(a, b) -> f a . g b) z x++instance Bitraversable Separated where+  bitraverse f g (Separated x) =+    Separated <$> traverse (\(a, b) -> (,) <$> f a <*> g b) x++-- | Map across a @Separated@ on the element values.+--+-- prop> fmap id (x :: Separated Int String) == x+--+-- prop> \a b -> fmap (+1) (a +: b +: emptySeparated) == a +: (1+b) +: emptySeparated+instance Functor (Separated a) where+  fmap =+    bimap id++-- | Applies functions with element values, using a zipping operation, appending+-- separators.+--+-- >>> (emptySeparated :: Separated [Int] (String -> [String])) <.> emptySeparated+-- []+--+-- >>> [1,2] +: (\s -> [s, reverse s, drop 1 s]) +: emptySeparated <.> [3,4,5] +: "abc" +: emptySeparated+-- [[1,2,3,4,5],["abc","cba","bc"]]+instance Semigroup a => Apply (Separated a) where+  (<.>) =+    separatedAp (<>)++-- | Applies functions with element values, using a zipping operation, appending+-- separators. The identity operation is an infinite list of the emptySeparated separator+-- and the given element value.+--+-- >>> (emptySeparated :: Separated [Int] (String -> [String])) <*> emptySeparated+-- []+--+-- >>> [1,2] +: (\s -> [s, reverse s, drop 1 s]) +: emptySeparated <*> [3,4,5] +: "abc" +: emptySeparated+-- [[1,2,3,4,5],["abc","cba","bc"]]+instance Monoid a => Applicative (Separated a) where    +  (<*>) =+    separatedAp mappend+  pure =+    Separated . repeat . (,) mempty++-- |+--+-- >>> show (emptySeparated :: Separated () ())+-- "[]"+--+-- >>> show ('x' +: (6 :: Int) +: emptySeparated)+-- "['x',6]"+instance (Show a, Show b) => Show (Separated a b) where+  show (Separated x) =+    showSeparated id x++-- |+--+-- >>> ('x' +: (6 :: Int) +: emptySeparated) <> ('y' +: 7 +: emptySeparated)+-- ['x',6,'y',7]+instance Semigroup (Separated a b) where+  Separated x <> Separated y =+    Separated (x <> y)    ++-- |+--+-- >>> ('x' +: (6 :: Int) +: emptySeparated) `mappend` ('y' +: 7 +: emptySeparated)+-- ['x',6,'y',7]+instance Monoid (Separated a b) where+  mappend =+    (<>)+  mempty =+    Separated mempty++----++instance Bifunctor Separated1 where+  bimap f g (Separated1 a x) =+    Separated1 (f a) (bimap g f x)++instance Bifoldable Separated1 where+  bifoldr f g z (Separated1 a x) = +    f a (bifoldr g f z x)++instance Bitraversable Separated1 where+  bitraverse f g (Separated1 a x) =+    Separated1 <$> f a <*> bitraverse g f x++-- | Map across a @Separated1@ on the separator values.+--+-- >>> fmap (+1) (set tailL (1 +: 'b' +: 2 +: 'c' +: emptySeparated) (singleSeparated 'a' :: Separated1 Char Int))+-- ['a',2,'b',3,'c']+--+-- prop> fmap id (x :: Separated1 Int String) == x+--+-- prop> fmap (+1) (singleSeparated x :: Separated1 Char Int) == singleSeparated x+instance Functor (Separated1 b) where+  fmap =+    bimap id++-- | Applies functions with separator values, using a zipping operation,+-- appending elements.+--+-- >>> [1,2] +: reverse +: [3,4] +: emptySeparated <.> [5,6,7] +: "abc" +: [8] +: emptySeparated+-- [[1,2,5,6,7],"cba",[3,4,8]]+instance Semigroup b => Apply (Separated1 b) where+  (<.>) =+    separated1Ap (<>)++-- | Applies functions with separator values, using a zipping operation,+-- appending elements. The identity operation is an infinite list of the emptySeparated+-- element and the given separator value.+--+-- >>> [1,2] +: reverse +: [3,4] +: emptySeparated <*> [5,6,7] +: "abc" +: [8] +: emptySeparated+-- [[1,2,5,6,7],"cba",[3,4,8]]+instance Monoid b => Applicative (Separated1 b) where    +  (<*>) =+    separated1Ap mappend+  pure =+    Separated1 mempty . (swapped #) . pure++instance (Show b, Show a) => Show (Separated1 b a) where+  show (Separated1 a (Separated x)) =+    showSeparated (show a:) x++-- | The isomorphism that swaps elements with their separators.+--+-- >>> swapped # emptyPesarated+-- []+--+-- >>> swapped # ('x' -: 6 -: emptyPesarated)+-- [6,'x']+--+-- >>> emptyPesarated ^. swapped+-- []+--+-- >>> ('x' -: 6 -: emptyPesarated) ^. swapped+-- [6,'x']+instance Swapped Pesarated where+  swapped =+    _Wrapped . swapped . from _Wrapped++instance Bifunctor Pesarated where+  bimap f g (Pesarated x) =+    Pesarated (bimap g f x)++instance Bifoldable Pesarated where+  bifoldr f g z (Pesarated x) =+    bifoldr g f z x++instance Bitraversable Pesarated where+  bitraverse f g (Pesarated x) =+    Pesarated <$> bitraverse g f x++-- | Map across a @Pesarated@ on the element values.+--+-- prop> fmap id (x :: Pesarated Int String) == x+--+-- prop> \a b -> fmap (+1) (a -: b -: emptyPesarated) == (1+a) -: b -: emptyPesarated+instance Functor (Pesarated a) where+  fmap f (Pesarated x) =+    Pesarated (first f x)++-- | Applies functions with element values, using a zipping operation, appending+-- separators.+--+-- >>> (emptyPesarated :: Pesarated [Int] (String -> [String])) <.> emptyPesarated+-- []+--+-- >>> (\s -> [s, reverse s, drop 1 s]) -: [1,2] -: emptyPesarated <.> "abc" -: [3,4,5] -: emptyPesarated+-- [["abc","cba","bc"],[1,2,3,4,5]]+instance Semigroup a => Apply (Pesarated a) where+  Pesarated f <.> Pesarated a =+    Pesarated ((swapped # f <.> swapped # a) ^. swapped)++-- | Applies functions with element values, using a zipping operation, appending+-- separators. The identity operation is an infinite list of the emptySeparated separator+-- and the given element value.+--+-- >>> (emptySeparated :: Separated [Int] (String -> [String])) <*> emptySeparated+-- []+--+-- >>> (\s -> [s, reverse s, drop 1 s]) -: [1,2] -: emptyPesarated <*> "abc" -: [3,4,5] -: emptyPesarated+-- [["abc","cba","bc"],[1,2,3,4,5]]+instance Monoid a => Applicative (Pesarated a) where+  Pesarated f <*> Pesarated a =+    Pesarated ((swapped # f <*> swapped # a) ^. swapped)+  pure a =+    Pesarated (pure a ^. swapped)++-- |+--+-- >>> show (emptyPesarated :: Pesarated () ())+-- "[]"+--+-- >>> show ('x' -: (6 :: Int) -: emptyPesarated)+-- "['x',6]"+instance (Show a, Show b) => Show (Pesarated b a) where+  show (Pesarated x) =+    show x++-- |+--+-- >>> ('x' -: (6 :: Int) -: emptyPesarated) <> ('y' -: 7 -: emptyPesarated)+-- ['x',6,'y',7]+instance Semigroup (Pesarated b a) where+  Pesarated a <> Pesarated b =+    Pesarated (a <> b)++-- |+--+-- >>> ('x' -: (6 :: Int) -: emptyPesarated) `mappend` ('y' -: 7 -: emptyPesarated)+-- ['x',6,'y',7]+instance Monoid (Pesarated b a) where+  Pesarated a `mappend` Pesarated b =+    Pesarated (a <> b)+  mempty =+    Pesarated mempty++instance Bifunctor Pesarated1 where+  bimap f g (Pesarated1 x) =+    Pesarated1 (bimap g f x)++instance Bifoldable Pesarated1 where+  bifoldr f g z (Pesarated1 x) =+    bifoldr g f z x++instance Bitraversable Pesarated1 where+  bitraverse f g (Pesarated1 x) =+    Pesarated1 <$> bitraverse g f x++-- | Map across a @Pesarated1@ on the separator values.+--+-- >>> fmap toUpper (set tailL (1 -: 'b' -: 2 -: 'c' -: empty) (singlePesarated 'z' :: Pesarated1 Int Char) :: Pesarated1 Int Char)+-- ['Z',1,'B',2,'C']+--+-- prop> fmap id (x :: Pesarated1 Int String) == x+--+-- prop> fmap (+1) (singlePesarated x :: Pesarated1 Char Int) == singlePesarated (x + 1)+instance Functor (Pesarated1 a) where+  fmap f (Pesarated1 x) =+    Pesarated1 (first f x)++-- | Applies functions with separator values, using a zipping operation,+-- appending elements.+--+-- >>> id -: [1,2] -: reverse -: [3,4] -: emptyPesarated <.> "def" -: [5,6,7] -: "abc" -: [8] -: emptyPesarated+-- ["def",[1,2,5,6,7],"cba",[3,4,8]]+instance Semigroup a => Apply (Pesarated1 a) where+  f <.> a =+    pesarated1Ap (<>) f a++-- | Applies functions with separator values, using a zipping operation,+-- appending elements. The identity operation is an infinite list of the emptySeparated+-- element and the given separator value.+--+-- >>> id -: [1,2] -: reverse -: [3,4] -: emptyPesarated <*> "def" -: [5,6,7] -: "abc" -: [8] -: emptyPesarated+-- ["def",[1,2,5,6,7],"cba",[3,4,8]]+instance Monoid a => Applicative (Pesarated1 a) where+  f <*> a =+    pesarated1Ap mappend f a+  pure a =+    Pesarated1 (Separated1 a (pure a))++instance (Show a, Show b) => Show (Pesarated1 a b) where+  show (Pesarated1 x) =+    show x++---- not exported++showSeparated ::+ (Show a, Show s, Functor f) =>+ (f String -> [String])+ -> f (s, a)+ -> String+showSeparated f x =+  '[' : intercalate "," (f (fmap (\(s, a) -> show s <> "," <> show a) x)) <> "]"++separatedAp ::+  (s -> s -> s)+  -> Separated s (a -> b)+  -> Separated s a+  -> Separated s b+separatedAp opp (Separated f) (Separated a) =+    Separated (zipWith (\(s, f') (t, a') -> (s `opp` t, f' a')) f a)  ++separated1Ap ::+  (a -> a -> a)+  -> Separated1 a (s -> t)+  -> Separated1 a s+  -> Separated1 a t+separated1Ap opp (Separated1 f (Separated fs)) (Separated1 a (Separated as)) =+    Separated1 (f `opp` a) (Separated (zipWith (\(s, f') (t, a') -> (s t, f' `opp` a')) fs as))++pesarated1Ap ::+  (a -> a -> a)+  -> Pesarated1 a (s -> t)+  -> Pesarated1 a s+  -> Pesarated1 a t+pesarated1Ap opp (Pesarated1 (Separated1 f (Separated fs))) (Pesarated1 (Separated1 a (Separated as))) =+  Pesarated1 (Separated1 (f a) (Separated (zipWith (\(s, f') (t, a') -> (s `opp` t, f' a')) fs as)))++-- | The isomorphism that shuffles the elements and separators one position.+--+-- >>> shift # ([], 6)+-- [6]+--+-- >>> shift # ([(5, 'x')], 6)+-- [5,'x',6]+--+-- >>> singleSeparated 6 ^. shift+-- ([],6)+--+-- >>> (5 +: 'x' +: singleSeparated 6) ^. shift+-- ([(5,'x')],6)+shift ::+  Iso (Separated1 a s) (Separated1 b t) ([(a, s)], a) ([(b, t)], b)+shift =+  let shiftR ([], a) =+        Separated1 a (Separated [])+      shiftR ((b, s):r, a) =+        let Separated1 z' (Separated w) = shiftR (r, b)+        in Separated1 z' (Separated ((s, a) : w))+      shiftL (Separated1 s' (Separated [])) =+        ([], s')+      shiftL (Separated1 s' (Separated ((a, t') : r))) =+        let (w, z) = shiftL (Separated1 t' (Separated r))+        in ((s', a) : w, z)+  in iso shiftL shiftR++makeWrapped ''Separated+makeWrapped ''Pesarated+makeWrapped ''Pesarated1
− src/Data/Separated/Separated.hs
@@ -1,443 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE FlexibleInstances #-}--module Data.Separated.Separated(-  Separated-, separated-, Separated1-, separated1--- * Viewing-, separated1Head-, separated1Tail--- Constructing-, empty-, (+-)-, single--- * Appending-, shift-, (.++.)-, (++.)-, (.++)--- * Alternating-, separatedBy-, separatedBy1-) where--import Control.Applicative(Alternative(many))-import Data.Bifoldable(Bifoldable(bifoldr))-import Data.Bitraversable(Bitraversable(bitraverse))-import Data.Functor.Apply as Apply((<.>))-import Data.List(intercalate, zipWith, repeat)-import Data.Monoid as Monoid(mappend)-import Data.Semigroup as Semigroup((<>))-import Data.Separated.SeparatedCons(SeparatedCons((+:), SeparatedConsF, SeparatedConsG))-import Data.String(String)-import Papa hiding ((<.>))---- $setup--- >>> :set -XNoImplicitPrelude--- >>> import Data.Char(toUpper)--- >>> import Data.Either(isLeft)--- >>> import Text.Parsec(parse, char, digit)--- >>> import Test.QuickCheck(Arbitrary(..))--- >>> instance (Arbitrary s, Arbitrary a) => Arbitrary (Separated s a) where arbitrary = fmap (^. separated) arbitrary--- >>> instance (Arbitrary a, Arbitrary s) => Arbitrary (Separated1 s a) where arbitrary = do a <- arbitrary; x <- arbitrary; return ((a, x) ^. separated1)---newtype Separated a b =-  Separated [(a, b)]-  deriving (Eq, Ord)--makeWrapped ''Separated---- | The isomorphism that swaps elements with their separators.------ >>> swapped # empty--- []------ >>> swapped # ('x' +: 6 +: empty)--- [6,'x']------ >>> empty ^. swapped--- []------ >>> ('x' +: 6 +: empty) ^. swapped--- [6,'x']-instance Swapped Separated where-  swapped =-    let swap = (\(Separated x) -> Separated (fmap (\(a, b) -> (b, a)) x))-    in iso swap swap--instance Bifunctor Separated where-  bimap f g (Separated x) =-    Separated (fmap (bimap f g) x)--instance Bifoldable Separated where-  bifoldr f g z (Separated x) =-    foldr (\(a, b) -> f a . g b) z x--instance Bitraversable Separated where-  bitraverse f g (Separated x) =-    Separated <$> traverse (\(a, b) -> (,) <$> f a <*> g b) x---- | Map across a @Separated@ on the element values.------ prop> fmap id (x :: Separated Int String) == x------ prop> \a b -> fmap (+1) (a +: b +: empty) == a +: (1+b) +: empty-instance Functor (Separated a) where-  fmap =-    bimap id---- | Applies functions with element values, using a zipping operation, appending--- separators.------ >>> (empty :: Separated [Int] (String -> [String])) <.> empty--- []------ >>> [1,2] +: (\s -> [s, reverse s, drop 1 s]) +: empty <.> [3,4,5] +: "abc" +: empty--- [[1,2,3,4,5],["abc","cba","bc"]]-instance Semigroup a => Apply (Separated a) where-  (<.>) =-    separatedAp (<>)---- | Applies functions with element values, using a zipping operation, appending--- separators. The identity operation is an infinite list of the empty separator--- and the given element value.------ >>> (empty :: Separated [Int] (String -> [String])) <*> empty--- []------ >>> [1,2] +: (\s -> [s, reverse s, drop 1 s]) +: empty <*> [3,4,5] +: "abc" +: empty--- [[1,2,3,4,5],["abc","cba","bc"]]-instance (Semigroup a, Monoid a) => Applicative (Separated a) where    -  (<*>) =-    separatedAp (<>)-  pure =-    Separated . repeat . (,) mempty--instance (Show a, Show b) => Show (Separated a b) where-  show (Separated x) =-    showSeparated id x--instance Semigroup (Separated a b) where-  Separated x <> Separated y =-    Separated (x <> y)    --instance Monoid (Separated a b) where-  mappend =-    (<>)-  mempty =-    Separated mempty--instance SeparatedCons Separated1 Separated where-  type SeparatedConsF Separated = Separated1-  type SeparatedConsG Separated1 = Separated-  s +: Separated1 a (Separated x) =-    Separated ((s, a) : x)--------data Separated1 b a =-  Separated1 b (Separated a b)-  deriving (Eq, Ord)--instance Bifunctor Separated1 where-  bimap f g (Separated1 a x) =-    Separated1 (f a) (bimap g f x)---- | Map across a @Separated1@ on the separator values.------ >>> fmap (+1) (set separated1Tail (1 +: 'b' +: 2 +: 'c' +: empty) (single 'a'))--- ['a',2,'b',3,'c']------ prop> fmap id (x :: Separated1 Int String) == x------ prop> fmap (+1) (single x) == single x-instance Functor (Separated1 b) where-  fmap =-    bimap id---- | Applies functions with separator values, using a zipping operation,--- appending elements.------ >>> [1,2] +: reverse +: [3,4] +: empty <.> [5,6,7] +: "abc" +: [8] +: empty--- [[1,2,5,6,7],"cba",[3,4,8]]-instance Semigroup b => Apply (Separated1 b) where-  (<.>) =-    separated1Ap (<>)--instance (Show b, Show a) => Show (Separated1 b a) where-  show (Separated1 a (Separated x)) =-    showSeparated (show a:) x-    --- | Applies functions with separator values, using a zipping operation,--- appending elements. The identity operation is an infinite list of the empty--- element and the given separator value.------ >>> [1,2] +: reverse +: [3,4] +: empty <*> [5,6,7] +: "abc" +: [8] +: empty--- [[1,2,5,6,7],"cba",[3,4,8]]-instance (Semigroup b, Monoid b) => Applicative (Separated1 b) where    -  (<*>) =-    separated1Ap (<>)-  pure =-    Separated1 mempty . (swapped #) . pure--instance SeparatedCons Separated Separated1 where-  type SeparatedConsF Separated1 = Separated-  type SeparatedConsG Separated = Separated1-  (+:) =-    Separated1---------- | The isomorphism to a list of pairs of element and separator values.------ >>> separated # empty--- []------ >>> separated # ('x' +: 6 +: empty)--- [('x',6)]------ >>> [] ^. separated--- []------ >>> [(6, [])] ^. separated--- [6,[]]-separated ::-  Iso [(a, b)] [(c, d)] (Separated a b) (Separated c d)-separated =-  from _Wrapped--empty ::-  Separated s a-empty =-  Separated []---- | The isomorphism to element values interspersed with a separator.------ >>> separated1 # (single 6)--- (6,[])------ >>> separated1 # (5 +: 'x' +: single 6)--- (5,['x',6])------ >>> (6, empty) ^. separated1--- [6]------ >>> (5, 'x' +- 6) ^. separated1--- [5,'x',6]-separated1 ::-  Iso (a, Separated s a) (b, Separated t b) (Separated1 a s) (Separated1 b t)-separated1 =-  iso (uncurry Separated1) (\(Separated1 a x) -> (a, x))---- | A lens on the first element value.------ >>> single 7 ^. separated1Head--- 7------ prop> single x ^. separated1Head == (x :: Int)-separated1Head ::-  Lens (Separated1 a t) (Separated1 a t) a a-separated1Head =-  from separated1 . _1---- | A lens on the tail.------ prop> (d +: e +: single x) ^. separated1Tail == e +: x +: empty-separated1Tail ::-  Lens (Separated1 a s) (Separated1 a t) (Separated s a) (Separated t a)-separated1Tail =-  from separated1 . _2---- | One element and one separator.------ >>> 7 +- "abc"--- [7,"abc"]------ >>> 7 +: "abc" +: 8 +- "def"--- [7,"abc",8,"def"]-(+-) ::-  s-  -> a-  -> Separated s a-s +- a =-  s +: single a--infixl 9 +----- | Zero element values interspersed with one element.------ >>> single 4--- [4]------ prop> single x ^. separated1Tail == empty-single ::-  a-  -> Separated1 a s-single a =-  Separated1 a empty---- | The isomorphism that shuffles the elements and separators one position.------ >>> shift # ([], 6)--- [6]------ >>> shift # ([(5, 'x')], 6)--- [5,'x',6]------ >>> single 6 ^. shift--- ([],6)------ >>> (5 +: 'x' +: single 6) ^. shift--- ([(5,'x')],6)-shift ::-  Iso (Separated1 a s) (Separated1 b t) ([(a, s)], a) ([(b, t)], b)-shift =-  let shiftR ([], a) =-        Separated1 a (Separated [])-      shiftR ((b, s):r, a) =-        let Separated1 z' (Separated w) = shiftR (r, b)-        in Separated1 z' (Separated ((s, a) : w))-      shiftL (Separated1 s' (Separated [])) =-        ([], s')-      shiftL (Separated1 s' (Separated ((a, t') : r))) =-        let (w, z) = shiftL (Separated1 t' (Separated r))-        in ((s', a) : w, z)-  in iso shiftL shiftR---- | Append two lists of separated values to produce a list of pairs of separator and element values.------ >>> single 7 .++. single 'a'--- [7,'a']------ 'a' +: single 7 .++. single 'b'--- ['a',7,'b']------ prop> a +: (b :: Separated Int Int) == a +: b --  (a +: (b .++. c)) == ((a +: b) .++ c)-(.++.) ::-   Separated1 s a-   -> Separated1 a s-   -> Separated s a-Separated1 s x .++. Separated1 t (Separated y) =-  let (q, r') = (s, x) ^. separated1 . shift-  in Separated (q <> ((r', t) : y)) --infixr 5 .++.---- | Append element values interspersed with a separator to a list of pairs of separator and element values.------ >>> empty ++. single 7--- [7]------ >>> empty ++. 6 +: 'x' +: single 7--- [6,'x',7]------ >>> 'w' +: empty ++. 6 +: 'x' +: single 7--- ['w',6,'x',7]-(++.) ::-  Separated s a-  -> Separated1 s a-  -> Separated1 s a-Separated x ++. Separated1 t y =-  let (z, w') = separated1 . shift # (x, t)-  in Separated1 z (w' <> y)--infixr 5 ++.---- | Append a list of pairs of separator and element values to element values interspersed with a separator.------ >>> single 7 .++ empty--- [7]------ >>> single 6 .++ 'x' +: 7 +: empty--- [6,'x',7]------ >>> 'w' +: single 6 .++ 'x' +: 7 +: empty--- ['w',6,'x',7]-(.++) ::-  Separated1 a s-  -> Separated s a-  -> Separated1 a s-Separated1 a x .++ y =-  Separated1 a (x <> y)--infixr 5 .++---- |------ >>> parse (separatedBy (char ',') digit) "test" ""--- Right []------ >>> isLeft (parse (separatedBy (char ',') digit) "test" ",")--- True------ >>> parse (separatedBy (char ',') digit) "test" ",1"--- Right [',','1']------ >>> isLeft (parse (separatedBy (char ',') digit) "test" ",1,")--- True------ >>> parse (separatedBy (char ',') digit) "test" ",1,2,3,4,5"--- Right [',','1',',','2',',','3',',','4',',','5']-separatedBy ::-  Alternative f =>-  f a-  -> f b-  -> f (Separated a b)-separatedBy a b =-  Separated <$>-    many-      ((,) <$> a <*> b)---- |------ >>> isLeft (parse (separatedBy1 (char ',') digit) "test" "")--- True------ >>> parse (separatedBy1 (char ',') digit) "test" ","--- Right [',']------ >>> isLeft (parse (separatedBy1 (char ',') digit) "test" ",1")--- True------ >>> parse (separatedBy1 (char ',') digit) "test" ",1,"--- Right [',','1',',']------ >>>  parse (separatedBy1 (char ',') digit) "test" ",1,2,3,4,5,"--- Right [',','1',',','2',',','3',',','4',',','5',',']-separatedBy1 ::-  Alternative f =>-  f b-  -> f a-  -> f (Separated1 b a)-separatedBy1 b a =-  Separated1 <$> b <*> separatedBy a b--showSeparated ::- (Show a, Show s, Functor f) =>- (f String -> [String])- -> f (s, a)- -> String-showSeparated f x =-  '[' : intercalate "," (f (fmap (\(s, a) -> show s <> "," <> show a) x)) <> "]"--separatedAp ::-  (s -> s -> s)-  -> Separated s (a -> b)-  -> Separated s a-  -> Separated s b-separatedAp opp (Separated f) (Separated a) =-    Separated (zipWith (\(s, f') (t, a') -> (s `opp` t, f' a')) f a)  --separated1Ap ::-  (a -> a -> a)-  -> Separated1 a (s -> t)-  -> Separated1 a s-  -> Separated1 a t-separated1Ap opp (Separated1 f (Separated fs)) (Separated1 a (Separated as)) =-    Separated1 (f `opp` a) (Separated (zipWith (\(s, f') (t, a') -> (s t, f' `opp` a')) fs as))
− src/Data/Separated/SeparatedCons.hs
@@ -1,18 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}--module Data.Separated.SeparatedCons(-  SeparatedCons(..)-) where---- | Prepend a value to a separated-like structure.-class (f ~ SeparatedConsF g, g ~ SeparatedConsG f) => SeparatedCons f g where-  type SeparatedConsF g :: * -> * -> *-  type SeparatedConsG f :: * -> * -> *-  (+:) ::-    a-    -> f b a-    -> g a b-  -infixr 5 +: