Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
14 changes: 10 additions & 4 deletions src/Data/List.purs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ module Data.List
, transpose

, foldM

, module Exports
) where

import Prelude
Expand All @@ -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
Expand Down Expand Up @@ -529,25 +535,25 @@ 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.
-- |
-- | ```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 ---------------------------------------------------------
Expand Down
12 changes: 9 additions & 3 deletions src/Data/List/Lazy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ module Data.List.Lazy
, transpose

, foldM

, module Exports
) where

import Prelude
Expand All @@ -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))
Expand Down Expand Up @@ -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 ---------------------------------------------------------
Expand Down
36 changes: 12 additions & 24 deletions src/Data/List/ZipList.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 7 additions & 5 deletions test/Test/Data/List.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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]
Expand Down
9 changes: 5 additions & 4 deletions test/Test/Data/List/Lazy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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]
Expand Down