diff --git a/bower.json b/bower.json index 1325b41..b3035b6 100644 --- a/bower.json +++ b/bower.json @@ -20,16 +20,13 @@ "package.json" ], "dependencies": { - "purescript-arrays": "^1.0.0", - "purescript-foldable-traversable": "^1.0.0", - "purescript-generics": "^1.0.0", - "purescript-lazy": "^1.0.0", - "purescript-unfoldable": "^1.0.0" + "purescript-generics": "v3.0.0", + "purescript-lazy": "^2.0.0", + "purescript-unfoldable": "^2.0.0" }, "devDependencies": { - "purescript-arrays": "^1.0.0", - "purescript-assert": "^1.0.0", - "purescript-console": "^1.0.0", + "purescript-assert": "^2.0.0", + "purescript-console": "^2.0.0", "purescript-math": "^2.0.0" } } diff --git a/src/Data/List.purs b/src/Data/List.purs index 3abaec5..bec0dd1 100644 --- a/src/Data/List.purs +++ b/src/Data/List.purs @@ -82,6 +82,8 @@ module Data.List , transpose , foldM + + , module Exports ) where import Prelude @@ -97,10 +99,14 @@ import Data.Foldable (class Foldable, foldl, foldr, any, intercalate) import Data.Generic (class Generic) import Data.Maybe (Maybe(..)) import Data.Monoid (class Monoid, mempty) +import Data.NonEmpty (NonEmpty, (:|)) import Data.Traversable (class Traversable, traverse, sequence) import Data.Tuple (Tuple(..)) import Data.Unfoldable (class Unfoldable, unfoldr) +import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports +import Data.Traversable (scanl, scanr) as Exports + -- | A strict linked list. -- | -- | A list is either empty (represented by the `Nil` constructor) or non-empty, in @@ -529,7 +535,7 @@ span _ xs = { init: Nil, rest: xs } -- | ``` -- | -- | Running time: `O(n)` -group :: forall a. Eq a => List a -> List (List a) +group :: forall a. Eq a => List a -> List (NonEmpty List a) group = groupBy (==) -- | Sort and then group the elements of a list into lists. @@ -537,17 +543,17 @@ group = groupBy (==) -- | ```purescript -- | group' [1,1,2,2,1] == [[1,1,1],[2,2]] -- | ``` -group' :: forall a. Ord a => List a -> List (List a) +group' :: forall a. Ord a => List a -> List (NonEmpty List a) group' = group <<< sort -- | Group equal, consecutive elements of a list into lists, using the specified -- | equivalence relation to determine equality. -- | -- | Running time: `O(n)` -groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (List a) +groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (NonEmpty List a) groupBy _ Nil = Nil groupBy eq (x : xs) = case span (eq x) xs of - { init: ys, rest: zs } -> (x : ys) : groupBy eq zs + { init: ys, rest: zs } -> (x :| ys) : groupBy eq zs -------------------------------------------------------------------------------- -- Set-like operations --------------------------------------------------------- diff --git a/src/Data/List/Lazy.purs b/src/Data/List/Lazy.purs index 94efe85..6254637 100644 --- a/src/Data/List/Lazy.purs +++ b/src/Data/List/Lazy.purs @@ -90,6 +90,8 @@ module Data.List.Lazy , transpose , foldM + + , module Exports ) where import Prelude @@ -105,10 +107,14 @@ import Data.Foldable (class Foldable, foldMap, foldl, foldr, any) import Data.Lazy (Lazy, defer, force) import Data.Maybe (Maybe(..), isNothing) import Data.Monoid (class Monoid, mempty) +import Data.NonEmpty (NonEmpty, (:|)) import Data.Traversable (class Traversable, traverse, sequence) import Data.Tuple (Tuple(..)) import Data.Unfoldable (class Unfoldable, unfoldr) +import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports +import Data.Traversable (scanl, scanr) as Exports + -- | A lazy linked list. newtype List a = List (Lazy (Step a)) @@ -569,20 +575,20 @@ span p xs = -- | ``` -- | -- | Running time: `O(n)` -group :: forall a. Eq a => List a -> List (List a) +group :: forall a. Eq a => List a -> List (NonEmpty List a) group = groupBy (==) -- | Group equal, consecutive elements of a list into lists, using the specified -- | equivalence relation to determine equality. -- | -- | Running time: `O(n)` -groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (List a) +groupBy :: forall a. (a -> a -> Boolean) -> List a -> List (NonEmpty List a) groupBy eq xs = List (go <$> runList xs) where go Nil = Nil go (Cons x xs) = case span (eq x) xs of - { init: ys, rest: zs } -> Cons (cons x ys) (groupBy eq zs) + { init: ys, rest: zs } -> Cons (x :| ys) (groupBy eq zs) -------------------------------------------------------------------------------- -- Set-like operations --------------------------------------------------------- diff --git a/src/Data/List/ZipList.purs b/src/Data/List/ZipList.purs index d1fe29e..265dbd3 100644 --- a/src/Data/List/ZipList.purs +++ b/src/Data/List/ZipList.purs @@ -3,53 +3,41 @@ module Data.List.ZipList ( ZipList(..) - , runZipList ) where import Prelude import Control.Alt (class Alt) import Control.Alternative (class Alternative) import Control.Plus (class Plus) -import Data.Foldable (class Foldable, foldMap, foldl, foldr) +import Data.Foldable (class Foldable) import Data.List.Lazy (List, repeat, zipWith) import Data.Monoid (class Monoid, mempty) -import Data.Traversable (class Traversable, traverse, sequence) +import Data.Newtype (class Newtype) +import Data.Traversable (class Traversable) import Partial.Unsafe (unsafeCrashWith) -- | `ZipList` is a newtype around `List` which provides a zippy -- | `Applicative` instance. newtype ZipList a = ZipList (List a) --- | Unpack a `ZipList` to obtain the underlying list. -runZipList :: forall a. ZipList a -> List a -runZipList (ZipList xs) = xs - instance showZipList :: Show a => Show (ZipList a) where show (ZipList xs) = "(ZipList " <> show xs <> ")" -instance eqZipList :: Eq a => Eq (ZipList a) where - eq z1 z2 = runZipList z1 `eq` runZipList z2 +derive instance newtypeZipList :: Newtype (ZipList a) _ + +derive newtype instance eqZipList :: Eq a => Eq (ZipList a) -instance ordZipList :: Ord a => Ord (ZipList a) where - compare z1 z2 = runZipList z1 `compare` runZipList z2 +derive newtype instance ordZipList :: Ord a => Ord (ZipList a) -instance semigroupZipList :: Semigroup (ZipList a) where - append z1 z2 = ZipList (runZipList z1 <> runZipList z2) +derive newtype instance semigroupZipList :: Semigroup (ZipList a) -instance monoidZipList :: Monoid (ZipList a) where - mempty = ZipList mempty +derive newtype instance monoidZipList :: Monoid (ZipList a) -instance foldableZipList :: Foldable ZipList where - foldl f b (ZipList xs) = foldl f b xs - foldr f b (ZipList xs) = foldr f b xs - foldMap f (ZipList xs) = foldMap f xs +derive newtype instance foldableZipList :: Foldable ZipList -instance traversableZipList :: Traversable ZipList where - traverse f (ZipList xs) = ZipList <$> traverse f xs - sequence (ZipList xs) = ZipList <$> sequence xs +derive newtype instance traversableZipList :: Traversable ZipList -instance functorZipList :: Functor ZipList where - map f (ZipList xs) = ZipList (map f xs) +derive newtype instance functorZipList :: Functor ZipList instance applyZipList :: Apply ZipList where apply (ZipList fs) (ZipList xs) = ZipList (zipWith ($) fs xs) diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index f391e77..dc1e591 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -6,9 +6,11 @@ import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) import Data.Foldable (foldMap, foldl) -import Data.List (List(Nil, Cons), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, init, tail, last, head, insertBy, insert, snoc, null, singleton, fromFoldable, transpose, mapWithIndex, (:)) +import Data.List (List(..), (..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, span, dropWhile, drop, takeWhile, take, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, init, tail, last, head, insertBy, insert, snoc, null, singleton, fromFoldable, transpose, mapWithIndex, (:)) import Data.Maybe (Maybe(..), isNothing, fromJust) -import Data.Monoid.Additive (Additive(Additive)) +import Data.Monoid.Additive (Additive(..)) +import Data.NonEmpty ((:|)) +import Data.NonEmpty as NE import Data.Tuple (Tuple(..)) import Data.Unfoldable (replicate, replicateA, unfoldr) @@ -232,13 +234,13 @@ testList = do assert $ spanResult.rest == l [4, 5, 6, 7] log "group should group consecutive equal elements into lists" - assert $ group (l [1, 2, 2, 3, 3, 3, 1]) == l [l [1], l [2, 2], l [3, 3, 3], l [1]] + assert $ group (l [1, 2, 2, 3, 3, 3, 1]) == l [NE.singleton 1, 2 :| l [2], 3 :| l [3, 3], NE.singleton 1] log "group' should sort then group consecutive equal elements into lists" - assert $ group' (l [1, 2, 2, 3, 3, 3, 1]) == l [l [1, 1], l [2, 2], l [3, 3, 3]] + assert $ group' (l [1, 2, 2, 3, 3, 3, 1]) == l [1 :| l [1], 2 :| l [2], 3 :| l [3, 3]] log "groupBy should group consecutive equal elements into lists based on an equivalence relation" - assert $ groupBy (\x y -> odd x && odd y) (l [1, 1, 2, 2, 3, 3]) == l [l [1, 1], l [2], l [2], l [3, 3]] + assert $ groupBy (\x y -> odd x && odd y) (l [1, 1, 2, 2, 3, 3]) == l [1 :| l [1], NE.singleton 2, NE.singleton 2, 3 :| l [3]] log "nub should remove duplicate elements from the list, keeping the first occurence" assert $ nub (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4] diff --git a/test/Test/Data/List/Lazy.purs b/test/Test/Data/List/Lazy.purs index b09ab92..23db981 100644 --- a/test/Test/Data/List/Lazy.purs +++ b/test/Test/Data/List/Lazy.purs @@ -2,14 +2,15 @@ module Test.Data.List.Lazy (testListLazy) where import Prelude +import Control.Lazy (defer) import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) -import Math ((%)) import Data.List.Lazy (List, nil, cons, singleton, transpose, take, iterate, filter, uncons, foldM, range, unzip, zip, length, zipWithA, replicate, repeat, zipWith, intersectBy, intersect, deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group, span, dropWhile, drop, takeWhile, slice, catMaybes, mapMaybe, filterM, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, init, tail, last, head, insertBy, insert, snoc, null, replicateM, fromFoldable, (:), (\\), (!!)) import Data.Maybe (Maybe(..), isNothing, fromJust) +import Data.NonEmpty ((:|)) +import Data.NonEmpty as NE import Data.Tuple (Tuple(..)) -import Control.Lazy (defer) import Partial.Unsafe (unsafePartial) @@ -222,13 +223,13 @@ testListLazy = do assert $ spanResult.rest == l [4, 5, 6, 7] log "group should group consecutive equal elements into lists" - assert $ group (l [1, 2, 2, 3, 3, 3, 1]) == l [l [1], l [2, 2], l [3, 3, 3], l [1]] + assert $ group (l [1, 2, 2, 3, 3, 3, 1]) == l [NE.singleton 1, 2 :| l [2], 3 :| l [3, 3], NE.singleton 1] -- log "group' should sort then group consecutive equal elements into lists" -- assert $ group' (l [1, 2, 2, 3, 3, 3, 1]) == l [l [1, 1], l [2, 2], l [3, 3, 3]] log "groupBy should group consecutive equal elements into lists based on an equivalence relation" - assert $ groupBy (\x y -> odd x && odd y) (l [1, 1, 2, 2, 3, 3]) == l [l [1, 1], l [2], l [2], l [3, 3]] + assert $ groupBy (\x y -> odd x && odd y) (l [1, 1, 2, 2, 3, 3]) == l [1 :| l [1], NE.singleton 2, NE.singleton 2, 3 :| l [3]] log "nub should remove duplicate elements from the list, keeping the first occurence" assert $ nub (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4]