diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c69237a..b5a0c9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,30 +6,29 @@ on: pull_request: branches: [master] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - uses: purescript-contrib/setup-purescript@main - with: - purescript: "unstable" - - - uses: actions/setup-node@v2 + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 with: - node-version: "14.x" + node-version: "24" - name: Install dependencies - run: | - npm install -g bower - npm install - bower install --production + run: npm install - name: Build source - run: npm run-script build + run: npm run build - name: Run tests - run: | - bower install - npm run-script test --if-present + run: npm test + + - name: Run benchmarks + run: npm run bench + + - name: Check formatting + run: npm run format:check diff --git a/.gitignore b/.gitignore index 7ebd961..c9c5856 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ /.* !/.gitignore !/.github/ +!/.tidyrc.json /bower_components/ /node_modules/ /output/ -package-lock.json +/package-lock.json +/spago.lock diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 0000000..9e39cf1 --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "ide", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "first", + "unicode": "never", + "width": null +} diff --git a/CHANGELOG.md b/CHANGELOG.md index db8662b..419a8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,17 @@ Bugfixes: Other improvements: +## [v7.0.1](https://github.com/purescript/purescript-lists/releases/tag/v7.0.1) - 2026-10-17 + +Other improvements: + +- Migrate from Bower/Pulp to Spago and update CI (#223 by @thomashoneyman). +- Explicitly use `join` for `concat` (#212). + ## [v7.0.0](https://github.com/purescript/purescript-lists/releases/tag/v7.0.0) - 2022-04-27 Breaking changes: + - Update project and deps to PureScript v0.15.0 (#203 by @JordanMartinez) - Drop deprecated `MonadZero` instance (#205 by @JordanMartinez) - Drop deprecated `group'` and `mapWithIndex` (#206 by @JordanMartinez) @@ -31,21 +39,25 @@ Other improvements: Breaking changes: New features: + - Added `cons` for `Lazy.NonEmptyList` (#143 by @matthewleon) Bugfixes: Other improvements: + - Fix ad-hoc usage of case expression (#202 by @JordanMartinez) ## [v6.0.1](https://github.com/purescript/purescript-lists/releases/tag/v6.0.1) - 2021-04-19 Other improvements: + - Fixed warnings revealed by v0.14.1 PS release (#198 by @JordanMartinez) ## [v6.0.0](https://github.com/purescript/purescript-lists/releases/tag/v6.0.0) - 2021-02-26 Breaking changes: + - Converted `nub`/`nubBy` to use ordering, rather than equality (#179) - Renamed `scanrLazy` to `scanlLazy` and fixed parameter ordering (#161) - Renamed `group'` to `groupAll` (#182) @@ -53,6 +65,7 @@ Breaking changes: - Updated the `Show` instances for (non empty) lazy lists (#181) New features: + - Added `nubEq`/`nubByEq` (#179) - Added `groupAllBy` (#182) - Added `Eq1` and `Ord1` instances to `NonEmptyList` and `LazyNonEmptyList` (#188) @@ -60,11 +73,12 @@ New features: Bugfixes: Other improvements: + - Fixed Lazy List docs where original list is returned instead of Nothing (#169) - Migrated to GitHub Actions (#177) - Changed `foldM` type signature to more closely match `foldl` (#165) - Improved `foldr` performance on large lists (#180) -- Generated changelog and add PR template (#187) +- Generated changelog and add PR template (#187) ## [v5.4.1](https://github.com/purescript/purescript-lists/releases/tag/v5.4.1) - 2019-05-06 @@ -308,6 +322,7 @@ Make `Apply` and `Bind` instances for `ListT` consistent. (@puffnfresh) ## [v0.6.0](https://github.com/purescript/purescript-lists/releases/tag/v0.6.0) - 2015-02-21 **This release requires PureScript v0.6.8 or later** + - Updated dependencies ## [v0.5.0](https://github.com/purescript/purescript-lists/releases/tag/v0.5.0) - 2015-01-10 @@ -320,44 +335,28 @@ Remove `scanl`, bump `foldable` dependency. ## [v0.3.9](https://github.com/purescript/purescript-lists/releases/tag/v0.3.9) - 2014-12-13 - - ## [v0.3.8](https://github.com/purescript/purescript-lists/releases/tag/v0.3.8) - 2014-12-09 Bump `unfoldable` dependency. ## [v0.3.7](https://github.com/purescript/purescript-lists/releases/tag/v0.3.7) - 2014-11-26 - - ## [v0.3.5](https://github.com/purescript/purescript-lists/releases/tag/v0.3.5) - 2014-11-18 Fixes for compiler version 0.6.1 ## [v0.3.4](https://github.com/purescript/purescript-lists/releases/tag/v0.3.4) - 2014-11-14 - - ## [v0.3.3](https://github.com/purescript/purescript-lists/releases/tag/v0.3.3) - 2014-11-08 - - ## [v0.3.2](https://github.com/purescript/purescript-lists/releases/tag/v0.3.2) - 2014-10-29 - - ## [v0.3.1](https://github.com/purescript/purescript-lists/releases/tag/v0.3.1) - 2014-10-06 - - ## [v0.3.0](https://github.com/purescript/purescript-lists/releases/tag/v0.3.0) - 2014-10-01 - `ListT` by @jdegoes ## [v0.2.0](https://github.com/purescript/purescript-lists/releases/tag/v0.2.0) - 2014-08-13 - - ## [v0.0.1](https://github.com/purescript/purescript-lists/releases/tag/v0.0.1) - 2014-07-07 - - diff --git a/LICENSE-GHC.md b/LICENSE-GHC.md index a2d787b..ecdd5c7 100644 --- a/LICENSE-GHC.md +++ b/LICENSE-GHC.md @@ -7,15 +7,15 @@ 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. + 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. + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - Neither name of the University nor the names of its contributors may be -used to endorse or promote products derived from this software without -specific prior written permission. + used to endorse or promote products derived from this software without + specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, @@ -29,4 +29,3 @@ 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. - diff --git a/bench/spago.yaml b/bench/spago.yaml new file mode 100644 index 0000000..ffd783a --- /dev/null +++ b/bench/spago.yaml @@ -0,0 +1,14 @@ +package: + name: lists-bench + build: + strict: true + pedanticPackages: true + dependencies: + - console: ">=6.0.0 <7.0.0" + - effect: ">=4.0.0 <5.0.0" + - foldable-traversable: ">=6.0.0 <7.0.0" + - integers: ">=6.0.0 <7.0.0" + - lists: "*" + - maybe: ">=6.0.0 <7.0.0" + - minibench: ">=4.0.0 <5.0.0" + - prelude: ">=6.0.0 <7.0.0" diff --git a/bench/Bench/Data/List.purs b/bench/src/Bench/Data/List.purs similarity index 93% rename from bench/Bench/Data/List.purs rename to bench/src/Bench/Data/List.purs index c40fe60..ddf28a6 100644 --- a/bench/Bench/Data/List.purs +++ b/bench/src/Bench/Data/List.purs @@ -1,9 +1,10 @@ module Bench.Data.List where import Prelude + import Data.Foldable (maximum) import Data.Int (pow) -import Data.List (List(..), take, range, foldr, length) +import Data.List (List(..), foldr, length, range, take) import Data.Maybe (fromMaybe) import Data.Traversable (traverse_) import Effect (Effect) diff --git a/bench/Main.purs b/bench/src/Main.purs similarity index 100% rename from bench/Main.purs rename to bench/src/Main.purs index 7fa5459..d960049 100644 --- a/bench/Main.purs +++ b/bench/src/Main.purs @@ -1,10 +1,10 @@ module Bench.Main where import Prelude -import Effect (Effect) -import Effect.Console (log) import Bench.Data.List (benchList) +import Effect (Effect) +import Effect.Console (log) main :: Effect Unit main = do diff --git a/bower.json b/bower.json deleted file mode 100644 index 62188ce..0000000 --- a/bower.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "purescript-lists", - "homepage": "https://github.com/purescript/purescript-lists", - "authors": [ - "Phil Freeman " - ], - "license": "BSD-3-Clause", - "repository": { - "type": "git", - "url": "https://github.com/purescript/purescript-lists.git" - }, - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "output", - "test", - "bower.json", - "package.json" - ], - "dependencies": { - "purescript-bifunctors": "^6.0.0", - "purescript-control": "^6.0.0", - "purescript-foldable-traversable": "^6.0.0", - "purescript-lazy": "^6.0.0", - "purescript-maybe": "^6.0.0", - "purescript-newtype": "^5.0.0", - "purescript-nonempty": "^7.0.0", - "purescript-partial": "^4.0.0", - "purescript-prelude": "^6.0.0", - "purescript-tailrec": "^6.0.0", - "purescript-tuples": "^7.0.0", - "purescript-unfoldable": "^6.0.0" - }, - "devDependencies": { - "purescript-arrays": "^7.0.0", - "purescript-assert": "^6.0.0", - "purescript-console": "^6.0.0", - "purescript-minibench": "^4.0.0" - } -} diff --git a/package.json b/package.json index be00cb4..016dc6a 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,18 @@ { "private": true, "scripts": { - "clean": "rimraf output && rimraf .pulp-cache", - "build": "pulp build -- --censor-lib --strict", - "test": "pulp test", - "bench:build": "purs compile 'bench/**/*.purs' 'src/**/*.purs' 'bower_components/*/src/**/*.purs'", - "bench:run": "node --expose-gc -e 'require(\"./output/Bench.Main/index.js\").main()'", - "bench": "npm run bench:build && npm run bench:run" + "build": "spago build", + "test": "spago test -p lists", + "bench:build": "spago build -p lists-bench", + "bench:run": "node --expose-gc --input-type=module -e 'import { main } from \"./output/Bench.Main/index.js\"; main()'", + "bench": "npm run bench:build && npm run bench:run", + "format": "purs-tidy format-in-place src test bench/src && oxfmt --write .", + "format:check": "purs-tidy check src test bench/src && oxfmt --check ." }, "devDependencies": { - "pulp": "16.0.0-0", - "purescript-psa": "^0.8.2", - "rimraf": "^3.0.2" + "oxfmt": "^0.73.0", + "purescript": "^0.15.16", + "purs-tidy": "^0.11.1", + "spago": "^1.0.5" } } diff --git a/spago.yaml b/spago.yaml new file mode 100644 index 0000000..e5d16b2 --- /dev/null +++ b/spago.yaml @@ -0,0 +1,35 @@ +package: + name: lists + description: Strict and lazy linked lists with helper functions and type class instances + build: + strict: true + pedanticPackages: true + publish: + version: 7.0.1 + license: BSD-3-Clause + location: + githubOwner: purescript + githubRepo: purescript-lists + dependencies: + - bifunctors: ">=6.0.0 <7.0.0" + - control: ">=6.0.0 <7.0.0" + - foldable-traversable: ">=6.0.0 <7.0.0" + - lazy: ">=6.0.0 <7.0.0" + - maybe: ">=6.0.0 <7.0.0" + - newtype: ">=5.0.0 <6.0.0" + - nonempty: ">=7.0.0 <8.0.0" + - partial: ">=4.0.0 <5.0.0" + - prelude: ">=6.0.0 <7.0.0" + - tailrec: ">=6.0.0 <7.0.0" + - tuples: ">=7.0.0 <8.0.0" + - unfoldable: ">=6.0.0 <7.0.0" + test: + main: Test.Main + strict: true + pedanticPackages: true + dependencies: + - arrays: ">=7.0.0 <8.0.0" + - assert: ">=6.0.0 <7.0.0" + - console: ">=6.0.0 <7.0.0" + - effect: ">=4.0.0 <5.0.0" +workspace: {} diff --git a/src/Data/List.purs b/src/Data/List.purs index 8046afd..73aa8b7 100644 --- a/src/Data/List.purs +++ b/src/Data/List.purs @@ -13,7 +13,8 @@ module Data.List , fromFoldable , singleton - , (..), range + , (..) + , range , some , someRec , many @@ -33,7 +34,8 @@ module Data.List , uncons , unsnoc - , (!!), index + , (!!) + , index , elemIndex , elemLastIndex , findIndex @@ -79,7 +81,8 @@ module Data.List , unionBy , delete , deleteBy - , (\\), difference + , (\\) + , difference , intersect , intersectBy @@ -102,8 +105,8 @@ import Control.Alternative (class Alternative) import Control.Lazy (class Lazy, defer) import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM, tailRecM2) import Data.Bifunctor (bimap) -import Data.Foldable (class Foldable, foldr, any, foldl) -import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports +import Data.Foldable (class Foldable, any, foldl, foldr) +import Data.Foldable (all, any, elem, find, findMap, fold, foldMap, foldl, foldr, intercalate, notElem) as Exports import Data.List.Internal (emptySet, insertAndLookupBy) import Data.List.Types (List(..), (:)) import Data.List.Types (NonEmptyList(..)) as NEL @@ -142,11 +145,13 @@ infix 8 range as .. -- | Create a list containing a range of integers, including both endpoints. range :: Int -> Int -> List Int -range start end | start == end = singleton start - | otherwise = go end start (if start > end then 1 else -1) Nil - where - go s e step rest | s == e = s : rest - | otherwise = go (s + step) e step (s : rest) +range start end + | start == end = singleton start + | otherwise = go end start (if start > end then 1 else -1) Nil + where + go s e step rest + | s == e = s : rest + | otherwise = go (s + step) e step (s : rest) -- | Attempt a computation multiple times, requiring at least one success. -- | @@ -218,7 +223,7 @@ insertBy _ x Nil = singleton x insertBy cmp x ys@(y : ys') = case cmp x y of GT -> y : (insertBy cmp x ys') - _ -> x : ys + _ -> x : ys -------------------------------------------------------------------------------- -- Non-indexed reads ----------------------------------------------------------- @@ -236,8 +241,8 @@ head (x : _) = Just x -- | Running time: `O(n)`. last :: List ~> Maybe last (x : Nil) = Just x -last (_ : xs) = last xs -last _ = Nothing +last (_ : xs) = last xs +last _ = Nothing -- | Get all but the first element of a list, or `Nothing` if the list is empty. -- | @@ -299,8 +304,9 @@ findIndex :: forall a. (a -> Boolean) -> List a -> Maybe Int findIndex fn = go 0 where go :: Int -> List a -> Maybe Int - go n (x : xs) | fn x = Just n - | otherwise = go (n + 1) xs + go n (x : xs) + | fn x = Just n + | otherwise = go (n + 1) xs go _ Nil = Nothing -- | Find the last index for which a predicate holds. @@ -314,7 +320,7 @@ findLastIndex fn xs = ((length xs - 1) - _) <$> findIndex fn (reverse xs) insertAt :: forall a. Int -> a -> List a -> Maybe (List a) insertAt 0 x xs = Just (x : xs) insertAt n x (y : ys) = (y : _) <$> insertAt (n - 1) x ys -insertAt _ _ _ = Nothing +insertAt _ _ _ = Nothing -- | Delete an element from a list at the specified index, returning a new -- | list or `Nothing` if the index is out-of-bounds. @@ -323,14 +329,14 @@ insertAt _ _ _ = Nothing deleteAt :: forall a. Int -> List a -> Maybe (List a) deleteAt 0 (_ : ys) = Just ys deleteAt n (y : ys) = (y : _) <$> deleteAt (n - 1) ys -deleteAt _ _ = Nothing +deleteAt _ _ = Nothing -- | Update the element at the specified index, returning a new -- | list or `Nothing` if the index is out-of-bounds. -- | -- | Running time: `O(n)` updateAt :: forall a. Int -> a -> List a -> Maybe (List a) -updateAt 0 x ( _ : xs) = Just (x : xs) +updateAt 0 x (_ : xs) = Just (x : xs) updateAt n x (x1 : xs) = (x1 : _) <$> updateAt (n - 1) x xs updateAt _ _ _ = Nothing @@ -353,7 +359,7 @@ alterAt 0 f (y : ys) = Just $ Nothing -> ys Just y' -> y' : ys alterAt n f (y : ys) = (y : _) <$> alterAt (n - 1) f ys -alterAt _ _ _ = Nothing +alterAt _ _ _ = Nothing -------------------------------------------------------------------------------- -- Transformations ------------------------------------------------------------- @@ -466,7 +472,7 @@ sortBy cmp = mergeAll <<< sequences merge :: List a -> List a -> List a merge as@(a : as') bs@(b : bs') | a `cmp` b == GT = b : merge as bs' - | otherwise = a : merge as' bs + | otherwise = a : merge as' bs merge Nil bs = bs merge as Nil = as @@ -484,7 +490,6 @@ derive instance newtypePattern :: Newtype (Pattern a) _ instance showPattern :: Show a => Show (Pattern a) where show (Pattern s) = "(Pattern " <> show s <> ")" - -- | If the list starts with the given prefix, return the portion of the -- | list left after removing it, as a Just value. Otherwise, return Nothing. -- | * `stripPrefix (Pattern (1:Nil)) (1:2:Nil) == Just (2:Nil)` @@ -628,9 +633,11 @@ groupAllBy p = groupBy (\x y -> p x y == EQ) <<< sortBy p partition :: forall a. (a -> Boolean) -> List a -> { yes :: List a, no :: List a } partition p xs = foldr select { no: Nil, yes: Nil } xs where - select x { no, yes } = if p x - then { no, yes: x : yes } - else { no: x : no, yes } + select x { no, yes } = + if p x then + { no, yes: x : yes } + else + { no: x : no, yes } -- | Returns all final segments of the argument, longest first. For example, -- | @@ -640,7 +647,7 @@ partition p xs = foldr select { no: Nil, yes: Nil } xs -- | Running time: `O(n)` tails :: forall a. List a -> List (List a) tails Nil = singleton Nil -tails list@(Cons _ tl)= list : tails tl +tails list@(Cons _ tl) = list : tails tl -------------------------------------------------------------------------------- -- Set-like operations --------------------------------------------------------- @@ -670,12 +677,15 @@ nub = nubBy compare nubBy :: forall a. (a -> a -> Ordering) -> List a -> List a nubBy p = reverse <<< go emptySet Nil where - go _ acc Nil = acc - go s acc (a : as) = - let { found, result: s' } = insertAndLookupBy p a s - in if found - then go s' acc as - else go s' (a : acc) as + go _ acc Nil = acc + go s acc (a : as) = + let + { found, result: s' } = insertAndLookupBy p a s + in + if found then + go s' acc as + else + go s' (a : acc) as -- | Remove duplicate elements from a list. -- | Keeps the first occurrence of each element in the input list, @@ -703,7 +713,7 @@ nubEq = nubByEq eq -- | -- | Running time: `O(n^2)` nubByEq :: forall a. (a -> a -> Boolean) -> List a -> List a -nubByEq _ Nil = Nil +nubByEq _ Nil = Nil nubByEq eq' (x : xs) = x : nubByEq eq' (filter (\y -> not (eq' x y)) xs) -- | Calculate the union of two lists. @@ -753,9 +763,9 @@ intersect = intersectBy (==) -- | -- | Running time: `O(n^2)` intersectBy :: forall a. (a -> a -> Boolean) -> List a -> List a -> List a -intersectBy _ Nil _ = Nil -intersectBy _ _ Nil = Nil -intersectBy eq xs ys = filter (\x -> any (eq x) ys) xs +intersectBy _ Nil _ = Nil +intersectBy _ _ Nil = Nil +intersectBy eq xs ys = filter (\x -> any (eq x) ys) xs -------------------------------------------------------------------------------- -- Zipping --------------------------------------------------------------------- diff --git a/src/Data/List/Internal.purs b/src/Data/List/Internal.purs index 5f5c950..3e5a84d 100644 --- a/src/Data/List/Internal.purs +++ b/src/Data/List/Internal.purs @@ -41,16 +41,16 @@ insertAndLookupBy comp k orig = down Nil orig case comp k k1 of EQ -> { found: true, result: orig } LT -> down (Cons (TwoLeft k1 right) ctx) left - _ -> down (Cons (TwoRight left k1) ctx) right + _ -> down (Cons (TwoRight left k1) ctx) right down ctx (Three left k1 mid k2 right) = case comp k k1 of EQ -> { found: true, result: orig } c1 -> case c1, comp k k2 of - _ , EQ -> { found: true, result: orig } - LT, _ -> down (Cons (ThreeLeft k1 mid k2 right) ctx) left + _, EQ -> { found: true, result: orig } + LT, _ -> down (Cons (ThreeLeft k1 mid k2 right) ctx) left GT, LT -> down (Cons (ThreeMiddle left k1 k2 right) ctx) mid - _ , _ -> down (Cons (ThreeRight left k1 mid k2) ctx) right + _, _ -> down (Cons (ThreeRight left k1 mid k2) ctx) right up :: List (TreeContext k) -> KickUp k -> Set k up Nil (KickUp left k' right) = Two left k' right diff --git a/src/Data/List/Lazy.purs b/src/Data/List/Lazy.purs index 8821753..8d87bcb 100644 --- a/src/Data/List/Lazy.purs +++ b/src/Data/List/Lazy.purs @@ -13,7 +13,8 @@ module Data.List.Lazy , fromFoldable , singleton - , (..), range + , (..) + , range , replicate , replicateM , some @@ -35,7 +36,8 @@ module Data.List.Lazy , init , uncons - , (!!), index + , (!!) + , index , elemIndex , elemLastIndex , findIndex @@ -78,7 +80,8 @@ module Data.List.Lazy , unionBy , delete , deleteBy - , (\\), difference + , (\\) + , difference , intersect , intersectBy @@ -102,11 +105,11 @@ import Control.Alt ((<|>)) import Control.Alternative (class Alternative) import Control.Lazy as Z import Control.Monad.Rec.Class as Rec -import Data.Foldable (class Foldable, foldr, any, foldl) -import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports +import Data.Foldable (class Foldable, any, foldl, foldr) +import Data.Foldable (all, any, elem, find, findMap, fold, foldMap, foldl, foldr, intercalate, notElem) as Exports import Data.Lazy (defer) import Data.List.Internal (emptySet, insertAndLookupBy) -import Data.List.Lazy.Types (List(..), Step(..), step, nil, cons, (:)) +import Data.List.Lazy.Types (List(..), Step(..), cons, nil, step, (:)) import Data.List.Lazy.Types (NonEmptyList(..)) as NEL import Data.Maybe (Maybe(..), isNothing) import Data.Newtype (class Newtype, unwrap) @@ -147,13 +150,17 @@ infix 8 range as .. -- | Create a list containing a range of integers, including both endpoints. range :: Int -> Int -> List Int range start end - | start > end = - let g x | x >= end = Just (Tuple x (x - 1)) - | otherwise = Nothing - in unfoldr g start - | otherwise = unfoldr f start - where - f x | x <= end = Just (Tuple x (x + 1)) + | start > end = + let + g x + | x >= end = Just (Tuple x (x - 1)) + | otherwise = Nothing + in + unfoldr g start + | otherwise = unfoldr f start + where + f x + | x <= end = Just (Tuple x (x + 1)) | otherwise = Nothing -- | Create a list with repeated instances of a value. @@ -173,7 +180,7 @@ replicateM n m -- | -- | The `Lazy` constraint is used to generate the result lazily, to ensure -- | termination. -some :: forall f a. Alternative f => Z.Lazy (f (List a)) => f a -> f (List a) +some :: forall f a. Alternative f => Z.Lazy (f (List a)) => f a -> f (List a) some v = cons <$> v <*> Z.defer (\_ -> many v) -- | Attempt a computation multiple times, returning as many successful results @@ -239,7 +246,7 @@ insertBy cmp x xs = List (go <$> unwrap xs) go ys@(Cons y ys') = case cmp x y of GT -> Cons y (insertBy cmp x ys') - _ -> Cons x (fromStep ys) + _ -> Cons x (fromStep ys) -------------------------------------------------------------------------------- -- Non-indexed reads ----------------------------------------------------------- @@ -320,10 +327,11 @@ findIndex fn = go 0 where go :: Int -> List a -> Maybe Int go n list = do - o <- uncons list - if fn o.head - then pure n - else go (n + 1) o.tail + o <- uncons list + if fn o.head then + pure n + else + go (n + 1) o.tail -- | Find the last index for which a predicate holds. findLastIndex :: forall a. (a -> Boolean) -> List a -> Maybe Int @@ -428,13 +436,12 @@ filter p = List <<< map go <<< unwrap -- | ``` filterM :: forall a m. Monad m => (a -> m Boolean) -> List a -> m (List a) filterM p list = - case uncons list of - Nothing -> pure nil - Just { head: x, tail: xs } -> do - b <- p x - xs' <- filterM p xs - pure if b then cons x xs' else xs' - + case uncons list of + Nothing -> pure nil + Just { head: x, tail: xs } -> do + b <- p x + xs' <- filterM p xs + pure if b then cons x xs' else xs' -- | Apply a function to each element in a list, keeping only the results which -- | contain a value. @@ -462,7 +469,6 @@ catMaybes = mapMaybe identity -- Sublists -------------------------------------------------------------------- -------------------------------------------------------------------------------- - -- | A newtype used in cases where there is a list to be matched. newtype Pattern a = Pattern (List a) @@ -473,7 +479,6 @@ derive instance newtypePattern :: Newtype (Pattern a) _ instance showPattern :: Show a => Show (Pattern a) where show (Pattern s) = "(Pattern " <> show s <> ")" - -- | If the list starts with the given prefix, return the portion of the -- | list left after removing it, as a Just value. Otherwise, return Nothing. -- | * `stripPrefix (Pattern (fromFoldable [1])) (fromFoldable [1,2]) == Just (fromFoldable [2])` @@ -498,9 +503,11 @@ slice start end xs = take (end - start) (drop start xs) -- | -- | Running time: `O(n)` where `n` is the number of elements to take. take :: forall a. Int -> List a -> List a -take n = if n <= 0 - then const nil - else List <<< map (go n) <<< unwrap +take n = + if n <= 0 then + const nil + else + List <<< map (go n) <<< unwrap where go :: Int -> Step a -> Step a go _ Nil = Nil @@ -584,10 +591,10 @@ groupBy eq = List <<< map go <<< unwrap -- | -- | Running time: `O(n)` partition :: forall a. (a -> Boolean) -> List a -> { yes :: List a, no :: List a } -partition f = foldr go {yes: nil, no: nil} +partition f = foldr go { yes: nil, no: nil } where - go x {yes: ys, no: ns} = - if f x then {yes: x : ys, no: ns} else {yes: ys, no: x : ns} + go x { yes: ys, no: ns } = + if f x then { yes: x : ys, no: ns } else { yes: ys, no: x : ns } -------------------------------------------------------------------------------- -- Set-like operations --------------------------------------------------------- @@ -609,13 +616,16 @@ nub = nubBy compare nubBy :: forall a. (a -> a -> Ordering) -> List a -> List a nubBy p = go emptySet where - go s (List l) = List (map (goStep s) l) - goStep _ Nil = Nil - goStep s (Cons a as) = - let { found, result: s' } = insertAndLookupBy p a s - in if found - then step (go s' as) - else Cons a (go s' as) + go s (List l) = List (map (goStep s) l) + goStep _ Nil = Nil + goStep s (Cons a as) = + let + { found, result: s' } = insertAndLookupBy p a s + in + if found then + step (go s' as) + else + Cons a (go s' as) -- | Remove duplicate elements from a list. -- | @@ -660,14 +670,16 @@ deleteBy :: forall a. (a -> a -> Boolean) -> a -> List a -> List a deleteBy eq x xs = List (go <$> unwrap xs) where go Nil = Nil - go (Cons y ys) | eq x y = step ys - | otherwise = Cons y (deleteBy eq x ys) + go (Cons y ys) + | eq x y = step ys + | otherwise = Cons y (deleteBy eq x ys) -- | Delete the first occurrence of each element in the second list from the first list. -- | -- | Running time: `O(n^2)` difference :: forall a. Eq a => List a -> List a -> List a difference = foldl (flip delete) + infix 5 difference as \\ -- | Calculate the intersection of two lists. @@ -756,25 +768,27 @@ transpose xs = -- | Perform a fold using a monadic step function. foldM :: forall m a b. Monad m => (b -> a -> m b) -> b -> List a -> m b foldM f b xs = - case uncons xs of - Nothing -> pure b - Just { head: a, tail: as } -> - f b a >>= \b' -> foldM f b' as + case uncons xs of + Nothing -> pure b + Just { head: a, tail: as } -> + f b a >>= \b' -> foldM f b' as -- | Perform a right fold lazily foldrLazy :: forall a b. Z.Lazy b => (a -> b -> b) -> b -> List a -> b foldrLazy op z = go where - go xs = case step xs of - Cons x xs' -> Z.defer \_ -> x `op` go xs' - Nil -> z + go xs = case step xs of + Cons x xs' -> Z.defer \_ -> x `op` go xs' + Nil -> z -- | Perform a left scan lazily scanlLazy :: forall a b. (b -> a -> b) -> b -> List a -> List b scanlLazy f acc xs = List (go <$> unwrap xs) where - go :: Step a -> Step b - go Nil = Nil - go (Cons x xs') = - let acc' = f acc x - in Cons acc' $ scanlLazy f acc' xs' + go :: Step a -> Step b + go Nil = Nil + go (Cons x xs') = + let + acc' = f acc x + in + Cons acc' $ scanlLazy f acc' xs' diff --git a/src/Data/List/Lazy/NonEmpty.purs b/src/Data/List/Lazy/NonEmpty.purs index d5d207d..0600ac0 100644 --- a/src/Data/List/Lazy/NonEmpty.purs +++ b/src/Data/List/Lazy/NonEmpty.purs @@ -21,11 +21,11 @@ module Data.List.Lazy.NonEmpty import Prelude import Data.Foldable (class Foldable) -import Data.Lazy (force, defer) +import Data.Lazy (defer, force) import Data.List.Lazy ((:)) import Data.List.Lazy as L import Data.List.Lazy.Types (NonEmptyList(..)) -import Data.Maybe (Maybe(..), maybe, fromMaybe) +import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.NonEmpty ((:|)) import Data.Tuple (Tuple(..)) import Data.Unfoldable (class Unfoldable, unfoldr) diff --git a/src/Data/List/Lazy/Types.purs b/src/Data/List/Lazy/Types.purs index 6a4163b..c9c745a 100644 --- a/src/Data/List/Lazy/Types.purs +++ b/src/Data/List/Lazy/Types.purs @@ -11,7 +11,7 @@ import Control.MonadPlus (class MonadPlus) import Control.Plus (class Plus) import Data.Eq (class Eq1, eq1) import Data.Foldable (class Foldable, foldMap, foldl, foldr) -import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex) +import Data.FoldableWithIndex (class FoldableWithIndex, foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex) import Data.Lazy (Lazy, defer, force) import Data.Maybe (Maybe(..), maybe) @@ -19,7 +19,7 @@ import Data.Newtype (class Newtype, unwrap) import Data.NonEmpty (NonEmpty, (:|)) import Data.NonEmpty as NE import Data.Ord (class Ord1, compare1) -import Data.Traversable (class Traversable, traverse, sequence) +import Data.Traversable (class Traversable, sequence, traverse) import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex) import Data.Tuple (Tuple(..), snd) import Data.Unfoldable (class Unfoldable, unfoldr1) @@ -63,11 +63,11 @@ derive instance newtypeList :: Newtype (List a) _ instance showList :: Show a => Show (List a) where show xs = "(fromFoldable [" - <> case step xs of - Nil -> "" - Cons x xs' -> - show x <> foldl (\shown x' -> shown <> "," <> show x') "" xs' - <> "])" + <> case step xs of + Nil -> "" + Cons x xs' -> + show x <> foldl (\shown x' -> shown <> "," <> show x') "" xs' + <> "])" instance eqList :: Eq a => Eq (List a) where eq = eq1 @@ -87,8 +87,8 @@ instance ord1List :: Ord1 List where compare1 xs ys = go (step xs) (step ys) where go Nil Nil = EQ - go Nil _ = LT - go _ Nil = GT + go Nil _ = LT + go _ Nil = GT go (Cons x xs') (Cons y ys') = case compare x y of EQ -> go (step xs') (step ys') @@ -117,7 +117,8 @@ instance functorWithIndexList :: FunctorWithIndex Int List where instance foldableList :: Foldable List where -- calls foldl on the reversed list - foldr op z xs = foldl (flip op) z (rev xs) where + foldr op z xs = foldl (flip op) z (rev xs) + where rev = foldl (flip cons) nil foldl op = go @@ -134,9 +135,9 @@ instance foldableWithIndexList :: FoldableWithIndex Int List where foldrWithIndex f b xs = -- as we climb the reversed list, we decrement the index snd $ foldl - (\(Tuple i b') a -> Tuple (i - 1) (f (i - 1) a b')) - (Tuple len b) - revList + (\(Tuple i b') a -> Tuple (i - 1) (f (i - 1) a b')) + (Tuple len b) + revList where Tuple len revList = rev (Tuple 0 nil) xs where @@ -147,13 +148,15 @@ instance foldableWithIndexList :: FoldableWithIndex Int List where foldMapWithIndex f = foldlWithIndex (\i acc -> append acc <<< f i) mempty instance unfoldable1List :: Unfoldable1 List where - unfoldr1 = go where + unfoldr1 = go + where go f b = Z.defer \_ -> case f b of Tuple a (Just b') -> a : go f b' Tuple a Nothing -> a : nil instance unfoldableList :: Unfoldable List where - unfoldr = go where + unfoldr = go + where go f b = Z.defer \_ -> case f b of Nothing -> nil Just (Tuple a b') -> a : go f b' @@ -199,9 +202,11 @@ instance extendList :: Extend List where Cons _ as -> f l : (foldr go { val: nil, acc: nil } as).val where - go a { val, acc } = - let acc' = a : acc - in { val: f acc' : val, acc: acc' } + go a { val, acc } = + let + acc' = a : acc + in + { val: f acc' : val, acc: acc' } newtype NonEmptyList a = NonEmptyList (Lazy (NonEmpty List a)) diff --git a/src/Data/List/NonEmpty.purs b/src/Data/List/NonEmpty.purs index 42fa49e..c512e0b 100644 --- a/src/Data/List/NonEmpty.purs +++ b/src/Data/List/NonEmpty.purs @@ -16,7 +16,8 @@ module Data.List.NonEmpty , init , uncons , unsnoc - , (!!), index + , (!!) + , index , elemIndex , elemLastIndex , findIndex @@ -63,22 +64,21 @@ module Data.List.NonEmpty import Prelude import Data.Foldable (class Foldable) +import Data.Foldable (all, any, elem, find, findMap, fold, foldMap, foldl, foldr, intercalate, notElem) as Exports import Data.List ((:)) import Data.List as L import Data.List.Types (NonEmptyList(..)) import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.NonEmpty ((:|)) import Data.NonEmpty as NE +import Data.Semigroup.Foldable (fold1, foldMap1, for1_, sequence1_, traverse1_) as Exports import Data.Semigroup.Traversable (sequence1) +import Data.Semigroup.Traversable (sequence1, traverse1, traverse1Default) as Exports +import Data.Traversable (scanl, scanr) as Exports import Data.Tuple (Tuple(..), fst, snd) import Data.Unfoldable (class Unfoldable, unfoldr) import Partial.Unsafe (unsafeCrashWith) -import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports -import Data.Semigroup.Foldable (fold1, foldMap1, for1_, sequence1_, traverse1_) as Exports -import Data.Semigroup.Traversable (sequence1, traverse1, traverse1Default) as Exports -import Data.Traversable (scanl, scanr) as Exports - -- | Internal function: any operation on a list that is guaranteed not to delete -- | all elements also applies to a NEL, this function is a helper for defining -- | those cases. diff --git a/src/Data/List/Partial.purs b/src/Data/List/Partial.purs index 7d7987f..df53f39 100644 --- a/src/Data/List/Partial.purs +++ b/src/Data/List/Partial.purs @@ -20,11 +20,11 @@ tail (Cons _ xs) = xs -- | Running time: `O(n)` last :: forall a. Partial => List a -> a last (Cons x Nil) = x -last (Cons _ xs) = last xs +last (Cons _ xs) = last xs -- | Get all but the last element of a non-empty list. -- | -- | Running time: `O(n)` init :: forall a. Partial => List a -> List a init (Cons _ Nil) = Nil -init (Cons x xs) = Cons x (init xs) +init (Cons x xs) = Cons x (init xs) diff --git a/src/Data/List/Types.purs b/src/Data/List/Types.purs index a44df65..04eab8b 100644 --- a/src/Data/List/Types.purs +++ b/src/Data/List/Types.purs @@ -17,7 +17,7 @@ import Control.MonadPlus (class MonadPlus) import Control.Plus (class Plus) import Data.Eq (class Eq1, eq1) import Data.Foldable (class Foldable, foldl, foldr, intercalate) -import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex) +import Data.FoldableWithIndex (class FoldableWithIndex, foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex) import Data.Maybe (Maybe(..), maybe) import Data.Newtype (class Newtype) @@ -46,10 +46,10 @@ instance eqList :: Eq a => Eq (List a) where instance eq1List :: Eq1 List where eq1 xs ys = go xs ys true where - go _ _ false = false - go Nil Nil acc = acc - go (x : xs') (y : ys') acc = go xs' ys' $ acc && (y == x) - go _ _ _ = false + go _ _ false = false + go Nil Nil acc = acc + go (x : xs') (y : ys') acc = go xs' ys' $ acc && (y == x) + go _ _ _ = false instance ordList :: Ord a => Ord (List a) where compare = compare1 @@ -117,9 +117,9 @@ instance foldableWithIndexList :: FoldableWithIndex Int List where foldrWithIndex f b xs = -- as we climb the reversed list, we decrement the index snd $ foldl - (\(Tuple i b') a -> Tuple (i - 1) (f (i - 1) a b')) - (Tuple len b) - revList + (\(Tuple i b') a -> Tuple (i - 1) (f (i - 1) a b')) + (Tuple len b) + revList where Tuple len revList = rev (Tuple 0 Nil) xs where @@ -150,7 +150,7 @@ instance traversableList :: Traversable List where instance traversableWithIndexList :: TraversableWithIndex Int List where traverseWithIndex f = map rev - <<< foldlWithIndex (\i acc -> lift2 (flip (:)) acc <<< f i) (pure Nil) + <<< foldlWithIndex (\i acc -> lift2 (flip (:)) acc <<< f i) (pure Nil) where rev = foldl (flip Cons) Nil @@ -183,8 +183,10 @@ instance extendList :: Extend List where f l : (foldr go { val: Nil, acc: Nil } as).val where go a' { val, acc } = - let acc' = a' : acc - in { val: f acc' : val, acc: acc' } + let + acc' = a' : acc + in + { val: f acc' : val, acc: acc' } newtype NonEmptyList a = NonEmptyList (NonEmpty List a) @@ -260,5 +262,5 @@ instance traversableWithIndexNonEmptyList :: TraversableWithIndex Int NonEmptyLi instance traversable1NonEmptyList :: Traversable1 NonEmptyList where traverse1 f (NonEmptyList (a :| as)) = foldl (\acc -> lift2 (flip nelCons) acc <<< f) (pure <$> f a) as - <#> case _ of NonEmptyList (x :| xs) → foldl (flip nelCons) (pure x) xs + <#> case _ of NonEmptyList (x :| xs) -> foldl (flip nelCons) (pure x) xs sequence1 = traverse1 identity diff --git a/src/Data/List/ZipList.purs b/src/Data/List/ZipList.purs index 09e334d..7245c33 100644 --- a/src/Data/List/ZipList.purs +++ b/src/Data/List/ZipList.purs @@ -54,13 +54,16 @@ instance plusZipList :: Plus ZipList where instance alternativeZipList :: Alternative ZipList -instance zipListIsNotBind - :: Fail (Text """ +instance zipListIsNotBind :: + Fail + ( Text + """ ZipList is not Bind. Any implementation would break the associativity law. Possible alternatives: Data.List.List Data.List.Lazy.List - """) - => Bind ZipList where - bind = unsafeCrashWith "bind: unreachable" + """ + ) => + Bind ZipList where + bind = unsafeCrashWith "bind: unreachable" diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index a96b6d7..1055f71 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -8,7 +8,7 @@ import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.Function (on) import Data.List (List(..), Pattern(..), alterAt, catMaybes, concat, concatMap, delete, deleteAt, deleteBy, drop, dropEnd, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, fromFoldable, group, groupAll, groupAllBy, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, last, length, mapMaybe, modifyAt, nub, nubBy, nubByEq, nubEq, null, partition, range, reverse, singleton, snoc, sort, sortBy, span, stripPrefix, tail, take, takeEnd, takeWhile, transpose, uncons, union, unionBy, unsnoc, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) import Data.List.NonEmpty as NEL -import Data.Maybe (Maybe(..), isNothing, fromJust) +import Data.Maybe (Maybe(..), fromJust, isNothing) import Data.Monoid.Additive (Additive(..)) import Data.NonEmpty ((:|)) import Data.Traversable (traverse) @@ -30,28 +30,28 @@ testList = do nel x xs = NEL.NonEmptyList $ x :| fromFoldable xs log "strip prefix" - assert $ stripPrefix (Pattern (1:Nil)) (1:2:Nil) == Just (2:Nil) - assert $ stripPrefix (Pattern Nil) (1:Nil) == Just (1:Nil) - assert $ stripPrefix (Pattern (2:Nil)) (1:Nil) == Nothing + assert $ stripPrefix (Pattern (1 : Nil)) (1 : 2 : Nil) == Just (2 : Nil) + assert $ stripPrefix (Pattern Nil) (1 : Nil) == Just (1 : Nil) + assert $ stripPrefix (Pattern (2 : Nil)) (1 : Nil) == Nothing log "singleton should construct an list with a single value" - assert $ singleton 1 == l [1] - assert $ singleton "foo" == l ["foo"] - assert $ singleton nil == l [l []] + assert $ singleton 1 == l [ 1 ] + assert $ singleton "foo" == l [ "foo" ] + assert $ singleton nil == l [ l [] ] log "range should create an inclusive list of integers for the specified start and end" - assert $ (range 0 5) == l [0, 1, 2, 3, 4, 5] - assert $ (range 2 (-3)) == l [2, 1, 0, -1, -2, -3] + assert $ (range 0 5) == l [ 0, 1, 2, 3, 4, 5 ] + assert $ (range 2 (-3)) == l [ 2, 1, 0, -1, -2, -3 ] log "replicate should produce an list containing an item a specified number of times" - assert $ replicate 3 true == l [true, true, true] - assert $ replicate 1 "foo" == l ["foo"] + assert $ replicate 3 true == l [ true, true, true ] + assert $ replicate 1 "foo" == l [ "foo" ] assert $ replicate 0 "foo" == l [] assert $ replicate (-1) "foo" == l [] log "replicateA should perform the monadic action the correct number of times" - assert $ replicateA 3 (Just 1) == Just (l [1, 1, 1]) - assert $ replicateA 1 (Just 1) == Just (l [1]) + assert $ replicateA 3 (Just 1) == Just (l [ 1, 1, 1 ]) + assert $ replicateA 1 (Just 1) == Just (l [ 1 ]) assert $ replicateA 0 (Just 1) == Just (l []) assert $ replicateA (-1) (Just 1) == Just (l []) @@ -59,53 +59,53 @@ testList = do -- many log "null should return false for non-empty lists" - assert $ null (l [1]) == false - assert $ null (l [1, 2, 3]) == false + assert $ null (l [ 1 ]) == false + assert $ null (l [ 1, 2, 3 ]) == false log "null should return true for an empty list" assert $ null nil == true log "length should return the number of items in an list" assert $ length nil == 0 - assert $ length (l [1]) == 1 - assert $ length (l [1, 2, 3, 4, 5]) == 5 + assert $ length (l [ 1 ]) == 1 + assert $ length (l [ 1, 2, 3, 4, 5 ]) == 5 log "length should be stack-safe" void $ pure $ length (range 1 100000) log "snoc should add an item to the end of an list" - assert $ l [1, 2, 3] `snoc` 4 == l [1, 2, 3, 4] - assert $ nil `snoc` 1 == l [1] + assert $ l [ 1, 2, 3 ] `snoc` 4 == l [ 1, 2, 3, 4 ] + assert $ nil `snoc` 1 == l [ 1 ] log "insert should add an item at the appropriate place in a sorted list" - assert $ insert 1.5 (l [1.0, 2.0, 3.0]) == l [1.0, 1.5, 2.0, 3.0] - assert $ insert 4 (l [1, 2, 3]) == l [1, 2, 3, 4] - assert $ insert 0 (l [1, 2, 3]) == l [0, 1, 2, 3] + assert $ insert 1.5 (l [ 1.0, 2.0, 3.0 ]) == l [ 1.0, 1.5, 2.0, 3.0 ] + assert $ insert 4 (l [ 1, 2, 3 ]) == l [ 1, 2, 3, 4 ] + assert $ insert 0 (l [ 1, 2, 3 ]) == l [ 0, 1, 2, 3 ] log "insertBy should add an item at the appropriate place in a sorted list using the specified comparison" - assert $ insertBy (flip compare) 4 (l [1, 2, 3]) == l [4, 1, 2, 3] - assert $ insertBy (flip compare) 0 (l [1, 2, 3]) == l [1, 2, 3, 0] + assert $ insertBy (flip compare) 4 (l [ 1, 2, 3 ]) == l [ 4, 1, 2, 3 ] + assert $ insertBy (flip compare) 0 (l [ 1, 2, 3 ]) == l [ 1, 2, 3, 0 ] log "head should return a Just-NEL.NonEmptyListped first value of a non-empty list" - assert $ head (l ["foo", "bar"]) == Just "foo" + assert $ head (l [ "foo", "bar" ]) == Just "foo" log "head should return Nothing for an empty list" assert $ head nil == Nothing log "last should return a Just-NEL.NonEmptyListped last value of a non-empty list" - assert $ last (l ["foo", "bar"]) == Just "bar" + assert $ last (l [ "foo", "bar" ]) == Just "bar" log "last should return Nothing for an empty list" assert $ last nil == Nothing log "tail should return a Just-NEL.NonEmptyListped list containing all the items in an list apart from the first for a non-empty list" - assert $ tail (l ["foo", "bar", "baz"]) == Just (l ["bar", "baz"]) + assert $ tail (l [ "foo", "bar", "baz" ]) == Just (l [ "bar", "baz" ]) log "tail should return Nothing for an empty list" assert $ tail nil == Nothing log "init should return a Just-NEL.NonEmptyListped list containing all the items in an list apart from the first for a non-empty list" - assert $ init (l ["foo", "bar", "baz"]) == Just (l ["foo", "bar"]) + assert $ init (l [ "foo", "bar", "baz" ]) == Just (l [ "foo", "bar" ]) log "init should return Nothing for an empty list" assert $ init nil == Nothing @@ -114,225 +114,225 @@ testList = do assert $ isNothing (uncons nil) log "uncons should split an list into a head and tail record when there is at least one item" - let u1 = uncons (l [1]) + let u1 = uncons (l [ 1 ]) assert $ unsafePartial (fromJust u1).head == 1 assert $ unsafePartial (fromJust u1).tail == l [] - let u2 = uncons (l [1, 2, 3]) + let u2 = uncons (l [ 1, 2, 3 ]) assert $ unsafePartial (fromJust u2).head == 1 - assert $ unsafePartial (fromJust u2).tail == l [2, 3] + assert $ unsafePartial (fromJust u2).tail == l [ 2, 3 ] log "unsnoc should return nothing when used on an empty list" assert $ isNothing (unsnoc nil) log "unsnoc should split an list into an init and last record when there is at least one item" - let v1 = unsnoc (l [1]) + let v1 = unsnoc (l [ 1 ]) assert $ unsafePartial (fromJust v1).init == l [] assert $ unsafePartial (fromJust v1).last == 1 - let v2 = unsnoc (l [1, 2, 3]) - assert $ unsafePartial (fromJust v2).init == l [1, 2] + let v2 = unsnoc (l [ 1, 2, 3 ]) + assert $ unsafePartial (fromJust v2).init == l [ 1, 2 ] assert $ unsafePartial (fromJust v2).last == 3 log "(!!) should return Just x when the index is within the bounds of the list" - assert $ l [1, 2, 3] !! 0 == (Just 1) - assert $ l [1, 2, 3] !! 1 == (Just 2) - assert $ l [1, 2, 3] !! 2 == (Just 3) + assert $ l [ 1, 2, 3 ] !! 0 == (Just 1) + assert $ l [ 1, 2, 3 ] !! 1 == (Just 2) + assert $ l [ 1, 2, 3 ] !! 2 == (Just 3) log "(!!) should return Nothing when the index is outside of the bounds of the list" - assert $ l [1, 2, 3] !! 6 == Nothing - assert $ l [1, 2, 3] !! (-1) == Nothing + assert $ l [ 1, 2, 3 ] !! 6 == Nothing + assert $ l [ 1, 2, 3 ] !! (-1) == Nothing log "elemIndex should return the index of an item that a predicate returns true for in an list" - assert $ elemIndex 1 (l [1, 2, 1]) == Just 0 - assert $ elemIndex 4 (l [1, 2, 1]) == Nothing + assert $ elemIndex 1 (l [ 1, 2, 1 ]) == Just 0 + assert $ elemIndex 4 (l [ 1, 2, 1 ]) == Nothing log "elemLastIndex should return the last index of an item in an list" - assert $ elemLastIndex 1 (l [1, 2, 1]) == Just 2 - assert $ elemLastIndex 4 (l [1, 2, 1]) == Nothing + assert $ elemLastIndex 1 (l [ 1, 2, 1 ]) == Just 2 + assert $ elemLastIndex 4 (l [ 1, 2, 1 ]) == Nothing log "findIndex should return the index of an item that a predicate returns true for in an list" - assert $ findIndex (_ /= 1) (l [1, 2, 1]) == Just 1 - assert $ findIndex (_ == 3) (l [1, 2, 1]) == Nothing + assert $ findIndex (_ /= 1) (l [ 1, 2, 1 ]) == Just 1 + assert $ findIndex (_ == 3) (l [ 1, 2, 1 ]) == Nothing log "findLastIndex should return the last index of an item in an list" - assert $ findLastIndex (_ /= 1) (l [2, 1, 2]) == Just 2 - assert $ findLastIndex (_ == 3) (l [2, 1, 2]) == Nothing + assert $ findLastIndex (_ /= 1) (l [ 2, 1, 2 ]) == Just 2 + assert $ findLastIndex (_ == 3) (l [ 2, 1, 2 ]) == Nothing log "insertAt should add an item at the specified index" - assert $ (insertAt 0 1 (l [2, 3])) == Just (l [1, 2, 3]) - assert $ (insertAt 1 1 (l [2, 3])) == Just (l [2, 1, 3]) - assert $ (insertAt 2 1 (l [2, 3])) == Just (l [2, 3, 1]) + assert $ (insertAt 0 1 (l [ 2, 3 ])) == Just (l [ 1, 2, 3 ]) + assert $ (insertAt 1 1 (l [ 2, 3 ])) == Just (l [ 2, 1, 3 ]) + assert $ (insertAt 2 1 (l [ 2, 3 ])) == Just (l [ 2, 3, 1 ]) log "insertAt should return Nothing if the index is out of range" assert $ (insertAt 2 1 nil) == Nothing log "deleteAt should remove an item at the specified index" - assert $ (deleteAt 0 (l [1, 2, 3])) == Just (l [2, 3]) - assert $ (deleteAt 1 (l [1, 2, 3])) == Just (l [1, 3]) + assert $ (deleteAt 0 (l [ 1, 2, 3 ])) == Just (l [ 2, 3 ]) + assert $ (deleteAt 1 (l [ 1, 2, 3 ])) == Just (l [ 1, 3 ]) log "deleteAt should return Nothing if the index is out of range" assert $ (deleteAt 1 nil) == Nothing log "updateAt should replace an item at the specified index" - assert $ (updateAt 0 9 (l [1, 2, 3])) == Just (l [9, 2, 3]) - assert $ (updateAt 1 9 (l [1, 2, 3])) == Just (l [1, 9, 3]) + assert $ (updateAt 0 9 (l [ 1, 2, 3 ])) == Just (l [ 9, 2, 3 ]) + assert $ (updateAt 1 9 (l [ 1, 2, 3 ])) == Just (l [ 1, 9, 3 ]) log "updateAt should return Nothing if the index is out of range" assert $ (updateAt 1 9 nil) == Nothing log "modifyAt should update an item at the specified index" - assert $ (modifyAt 0 (_ + 1) (l [1, 2, 3])) == Just (l [2, 2, 3]) - assert $ (modifyAt 1 (_ + 1) (l [1, 2, 3])) == Just (l [1, 3, 3]) + assert $ (modifyAt 0 (_ + 1) (l [ 1, 2, 3 ])) == Just (l [ 2, 2, 3 ]) + assert $ (modifyAt 1 (_ + 1) (l [ 1, 2, 3 ])) == Just (l [ 1, 3, 3 ]) log "modifyAt should return Nothing if the index is out of range" assert $ (modifyAt 1 (_ + 1) nil) == Nothing log "alterAt should update an item at the specified index when the function returns Just" - assert $ (alterAt 0 (Just <<< (_ + 1)) (l [1, 2, 3])) == Just (l [2, 2, 3]) - assert $ (alterAt 1 (Just <<< (_ + 1)) (l [1, 2, 3])) == Just (l [1, 3, 3]) + assert $ (alterAt 0 (Just <<< (_ + 1)) (l [ 1, 2, 3 ])) == Just (l [ 2, 2, 3 ]) + assert $ (alterAt 1 (Just <<< (_ + 1)) (l [ 1, 2, 3 ])) == Just (l [ 1, 3, 3 ]) log "alterAt should drop an item at the specified index when the function returns Nothing" - assert $ (alterAt 0 (const Nothing) (l [1, 2, 3])) == Just (l [2, 3]) - assert $ (alterAt 1 (const Nothing) (l [1, 2, 3])) == Just (l [1, 3]) + assert $ (alterAt 0 (const Nothing) (l [ 1, 2, 3 ])) == Just (l [ 2, 3 ]) + assert $ (alterAt 1 (const Nothing) (l [ 1, 2, 3 ])) == Just (l [ 1, 3 ]) log "alterAt should return Nothing if the index is out of range" assert $ (alterAt 1 (Just <<< (_ + 1)) nil) == Nothing log "reverse should reverse the order of items in an list" - assert $ (reverse (l [1, 2, 3])) == l [3, 2, 1] + assert $ (reverse (l [ 1, 2, 3 ])) == l [ 3, 2, 1 ] assert $ (reverse nil) == nil log "concat should join an list of lists" - assert $ (concat (l [l [1, 2], l [3, 4]])) == l [1, 2, 3, 4] - assert $ (concat (l [l [1], nil])) == l [1] - assert $ (concat (l [nil, nil])) == nil + assert $ (concat (l [ l [ 1, 2 ], l [ 3, 4 ] ])) == l [ 1, 2, 3, 4 ] + assert $ (concat (l [ l [ 1 ], nil ])) == l [ 1 ] + assert $ (concat (l [ nil, nil ])) == nil log "concatMap should be equivalent to (concat <<< map)" - assert $ concatMap doubleAndOrig (l [1, 2, 3]) == concat (map doubleAndOrig (l [1, 2, 3])) + assert $ concatMap doubleAndOrig (l [ 1, 2, 3 ]) == concat (map doubleAndOrig (l [ 1, 2, 3 ])) log "filter should remove items that don't match a predicate" - assert $ filter odd (range 0 10) == l [1, 3, 5, 7, 9] + assert $ filter odd (range 0 10) == l [ 1, 3, 5, 7, 9 ] log "filterM should remove items that don't match a predicate while using a monadic behaviour" - assert $ filterM (Just <<< odd) (range 0 10) == Just (l [1, 3, 5, 7, 9]) + assert $ filterM (Just <<< odd) (range 0 10) == Just (l [ 1, 3, 5, 7, 9 ]) assert $ filterM (const Nothing) (range 0 10) == Nothing log "mapMaybe should transform every item in an list, throwing out Nothing values" - assert $ mapMaybe (\x -> if x /= 0 then Just x else Nothing) (l [0, 1, 0, 0, 2, 3]) == l [1, 2, 3] + assert $ mapMaybe (\x -> if x /= 0 then Just x else Nothing) (l [ 0, 1, 0, 0, 2, 3 ]) == l [ 1, 2, 3 ] log "catMaybe should take an list of Maybe values and throw out Nothings" - assert $ catMaybes (l [Nothing, Just 2, Nothing, Just 4]) == l [2, 4] + assert $ catMaybes (l [ Nothing, Just 2, Nothing, Just 4 ]) == l [ 2, 4 ] log "sort should reorder a list into ascending order based on the result of compare" - assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6] + assert $ sort (l [ 1, 3, 2, 5, 6, 4 ]) == l [ 1, 2, 3, 4, 5, 6 ] log "sortBy should reorder a list into ascending order based on the result of a comparison function" - assert $ sortBy (flip compare) (l [1, 3, 2, 5, 6, 4]) == l [6, 5, 4, 3, 2, 1] + assert $ sortBy (flip compare) (l [ 1, 3, 2, 5, 6, 4 ]) == l [ 6, 5, 4, 3, 2, 1 ] log "take should keep the specified number of items from the front of an list, discarding the rest" - assert $ (take 1 (l [1, 2, 3])) == l [1] - assert $ (take 2 (l [1, 2, 3])) == l [1, 2] + assert $ (take 1 (l [ 1, 2, 3 ])) == l [ 1 ] + assert $ (take 2 (l [ 1, 2, 3 ])) == l [ 1, 2 ] assert $ (take 1 nil) == nil - assert $ (take 0 (l [1, 2])) == l [] - assert $ (take (-1) (l [1, 2])) == l [] + assert $ (take 0 (l [ 1, 2 ])) == l [] + assert $ (take (-1) (l [ 1, 2 ])) == l [] log "takeEnd should keep the specified number of items from the end of an list, discarding the rest" - assert $ (takeEnd 1 (l [1, 2, 3])) == l [3] - assert $ (takeEnd 2 (l [1, 2, 3])) == l [2, 3] + assert $ (takeEnd 1 (l [ 1, 2, 3 ])) == l [ 3 ] + assert $ (takeEnd 2 (l [ 1, 2, 3 ])) == l [ 2, 3 ] assert $ (takeEnd 1 nil) == nil - assert $ (takeEnd 2 (l [1])) == l [1] + assert $ (takeEnd 2 (l [ 1 ])) == l [ 1 ] log "takeWhile should keep all values that match a predicate from the front of an list" - assert $ (takeWhile (_ /= 2) (l [1, 2, 3])) == l [1] - assert $ (takeWhile (_ /= 3) (l [1, 2, 3])) == l [1, 2] + assert $ (takeWhile (_ /= 2) (l [ 1, 2, 3 ])) == l [ 1 ] + assert $ (takeWhile (_ /= 3) (l [ 1, 2, 3 ])) == l [ 1, 2 ] assert $ (takeWhile (_ /= 1) nil) == nil log "drop should remove the specified number of items from the front of an list" - assert $ (drop 1 (l [1, 2, 3])) == l [2, 3] - assert $ (drop 2 (l [1, 2, 3])) == l [3] + assert $ (drop 1 (l [ 1, 2, 3 ])) == l [ 2, 3 ] + assert $ (drop 2 (l [ 1, 2, 3 ])) == l [ 3 ] assert $ (drop 1 nil) == nil - assert $ (drop (-1) (l [1, 2, 3])) == l [1, 2, 3] + assert $ (drop (-1) (l [ 1, 2, 3 ])) == l [ 1, 2, 3 ] log "dropEnd should remove the specified number of items from the end of an list" - assert $ (dropEnd 1 (l [1, 2, 3])) == l [1, 2] - assert $ (dropEnd 2 (l [1, 2, 3])) == l [1] + assert $ (dropEnd 1 (l [ 1, 2, 3 ])) == l [ 1, 2 ] + assert $ (dropEnd 2 (l [ 1, 2, 3 ])) == l [ 1 ] assert $ (dropEnd 1 nil) == nil log "dropWhile should remove all values that match a predicate from the front of an list" - assert $ (dropWhile (_ /= 1) (l [1, 2, 3])) == l [1, 2, 3] - assert $ (dropWhile (_ /= 2) (l [1, 2, 3])) == l [2, 3] + assert $ (dropWhile (_ /= 1) (l [ 1, 2, 3 ])) == l [ 1, 2, 3 ] + assert $ (dropWhile (_ /= 2) (l [ 1, 2, 3 ])) == l [ 2, 3 ] assert $ (dropWhile (_ /= 1) nil) == nil log "span should split an list in two based on a predicate" - let spanResult = span (_ < 4) (l [1, 2, 3, 4, 5, 6, 7]) - assert $ spanResult.init == l [1, 2, 3] - assert $ spanResult.rest == l [4, 5, 6, 7] + let spanResult = span (_ < 4) (l [ 1, 2, 3, 4, 5, 6, 7 ]) + assert $ spanResult.init == l [ 1, 2, 3 ] + 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 [NEL.singleton 1, NEL.NonEmptyList (2 :| l [2]), NEL.NonEmptyList (3 :| l [3, 3]), NEL.singleton 1] + assert $ group (l [ 1, 2, 2, 3, 3, 3, 1 ]) == l [ NEL.singleton 1, NEL.NonEmptyList (2 :| l [ 2 ]), NEL.NonEmptyList (3 :| l [ 3, 3 ]), NEL.singleton 1 ] log "groupAll should group equal elements into lists" - assert $ groupAll (l [1, 2, 2, 3, 3, 3, 1]) == l [NEL.NonEmptyList (1 :| l [1]), NEL.NonEmptyList (2 :| l [2]), NEL.NonEmptyList (3 :| l [3, 3])] + assert $ groupAll (l [ 1, 2, 2, 3, 3, 3, 1 ]) == l [ NEL.NonEmptyList (1 :| l [ 1 ]), NEL.NonEmptyList (2 :| l [ 2 ]), NEL.NonEmptyList (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 [NEL.NonEmptyList (1 :| l [1]), NEL.singleton 2, NEL.singleton 2, NEL.NonEmptyList (3 :| l [3])] + assert $ groupBy (\x y -> odd x && odd y) (l [ 1, 1, 2, 2, 3, 3 ]) == l [ NEL.NonEmptyList (1 :| l [ 1 ]), NEL.singleton 2, NEL.singleton 2, NEL.NonEmptyList (3 :| l [ 3 ]) ] log "groupAllBy should sort then group equal elements into lists based on a comparison function" - assert $ groupAllBy (compare `on` (_ `div` 10)) (l [32, 31, 21, 22, 11, 33]) == l [nel 11 [], nel 21 [22], nel 32 [31, 33]] + assert $ groupAllBy (compare `on` (_ `div` 10)) (l [ 32, 31, 21, 22, 11, 33 ]) == l [ nel 11 [], nel 21 [ 22 ], nel 32 [ 31, 33 ] ] log "partition should separate a list into a tuple of lists that do and do not satisfy a predicate" - let partitioned = partition (_ > 2) (l [1, 5, 3, 2, 4]) - assert $ partitioned.yes == l [5, 3, 4] - assert $ partitioned.no == l [1, 2] + let partitioned = partition (_ > 2) (l [ 1, 5, 3, 2, 4 ]) + assert $ partitioned.yes == l [ 5, 3, 4 ] + assert $ partitioned.no == l [ 1, 2 ] log "nub should remove duplicate elements from the list, keeping the first occurrence" - assert $ nub (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4] + assert $ nub (l [ 1, 2, 2, 3, 4, 1 ]) == l [ 1, 2, 3, 4 ] log "nubBy should remove duplicate items from the list using a supplied predicate" let nubPred = compare `on` Array.length - assert $ nubBy nubPred (l [[1],[2],[3,4]]) == l [[1],[3,4]] + assert $ nubBy nubPred (l [ [ 1 ], [ 2 ], [ 3, 4 ] ]) == l [ [ 1 ], [ 3, 4 ] ] log "nubEq should remove duplicate elements from the list, keeping the first occurrence" - assert $ nubEq (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4] + assert $ nubEq (l [ 1, 2, 2, 3, 4, 1 ]) == l [ 1, 2, 3, 4 ] log "nubByEq should remove duplicate items from the list using a supplied predicate" let mod3eq = eq `on` \n -> mod n 3 - assert $ nubByEq mod3eq (l [1, 3, 4, 5, 6]) == l [1, 3, 5] + assert $ nubByEq mod3eq (l [ 1, 3, 4, 5, 6 ]) == l [ 1, 3, 5 ] log "union should produce the union of two lists" - assert $ union (l [1, 2, 3]) (l [2, 3, 4]) == l [1, 2, 3, 4] - assert $ union (l [1, 1, 2, 3]) (l [2, 3, 4]) == l [1, 1, 2, 3, 4] + assert $ union (l [ 1, 2, 3 ]) (l [ 2, 3, 4 ]) == l [ 1, 2, 3, 4 ] + assert $ union (l [ 1, 1, 2, 3 ]) (l [ 2, 3, 4 ]) == l [ 1, 1, 2, 3, 4 ] log "unionBy should produce the union of two lists using the specified equality relation" - assert $ unionBy (\_ y -> y < 5) (l [1, 2, 3]) (l [2, 3, 4, 5, 6]) == l [1, 2, 3, 5, 6] + assert $ unionBy (\_ y -> y < 5) (l [ 1, 2, 3 ]) (l [ 2, 3, 4, 5, 6 ]) == l [ 1, 2, 3, 5, 6 ] log "delete should remove the first matching item from an list" - assert $ delete 1 (l [1, 2, 1]) == l [2, 1] - assert $ delete 2 (l [1, 2, 1]) == l [1, 1] + assert $ delete 1 (l [ 1, 2, 1 ]) == l [ 2, 1 ] + assert $ delete 2 (l [ 1, 2, 1 ]) == l [ 1, 1 ] log "deleteBy should remove the first equality-relation-matching item from an list" - assert $ deleteBy (/=) 2 (l [1, 2, 1]) == l [2, 1] - assert $ deleteBy (/=) 1 (l [1, 2, 1]) == l [1, 1] + assert $ deleteBy (/=) 2 (l [ 1, 2, 1 ]) == l [ 2, 1 ] + assert $ deleteBy (/=) 1 (l [ 1, 2, 1 ]) == l [ 1, 1 ] log "(\\\\) should return the difference between two lists" - assert $ l [1, 2, 3, 4, 3, 2, 1] \\ l [1, 1, 2, 3] == l [4, 3, 2] + assert $ l [ 1, 2, 3, 4, 3, 2, 1 ] \\ l [ 1, 1, 2, 3 ] == l [ 4, 3, 2 ] log "intersect should return the intersection of two lists" - assert $ intersect (l [1, 2, 3, 4, 3, 2, 1]) (l [1, 1, 2, 3]) == l [1, 2, 3, 3, 2, 1] + assert $ intersect (l [ 1, 2, 3, 4, 3, 2, 1 ]) (l [ 1, 1, 2, 3 ]) == l [ 1, 2, 3, 3, 2, 1 ] log "intersectBy should return the intersection of two lists using the specified equivalence relation" - assert $ intersectBy (\x y -> (x * 2) == y) (l [1, 2, 3]) (l [2, 6]) == l [1, 3] + assert $ intersectBy (\x y -> (x * 2) == y) (l [ 1, 2, 3 ]) (l [ 2, 6 ]) == l [ 1, 3 ] log "zipWith should use the specified function to zip two lists together" - assert $ zipWith (\x y -> l [show x, y]) (l [1, 2, 3]) (l ["a", "b", "c"]) == l [l ["1", "a"], l ["2", "b"], l ["3", "c"]] + assert $ zipWith (\x y -> l [ show x, y ]) (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == l [ l [ "1", "a" ], l [ "2", "b" ], l [ "3", "c" ] ] log "zipWithA should use the specified function to zip two lists together" - assert $ zipWithA (\x y -> Just $ Tuple x y) (l [1, 2, 3]) (l ["a", "b", "c"]) == Just (l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) + assert $ zipWithA (\x y -> Just $ Tuple x y) (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == Just (l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) log "zip should use the specified function to zip two lists together" - assert $ zip (l [1, 2, 3]) (l ["a", "b", "c"]) == l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] + assert $ zip (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] log "unzip should deconstruct a list of tuples into a tuple of lists" - assert $ unzip (l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) == Tuple (l [1, 2, 3]) (l ["a", "b", "c"]) + assert $ unzip (l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) == Tuple (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) log "foldM should perform a fold using a monadic step function" assert $ foldM (\x y -> Just (x + y)) 0 (range 1 10) == Just 55 @@ -363,32 +363,32 @@ testList = do void $ pure $ foldMapWithIndex (\i _ -> Additive i) $ range 1 100000 log "foldMapWithIndex should be left-to-right" - assert $ foldMapWithIndex (\i _ -> show i) (fromFoldable [0, 0, 0]) == "012" + assert $ foldMapWithIndex (\i _ -> show i) (fromFoldable [ 0, 0, 0 ]) == "012" log "unfoldable replicate should be stack-safe" void $ pure $ length $ replicate 100000 1 log "unfoldr should maintain order" - assert $ (1..5) == unfoldr step 1 + assert $ (1 .. 5) == unfoldr step 1 log "unfoldr1 should maintain order" - assert $ (1..5) == unfoldr1 step1 1 + assert $ (1 .. 5) == unfoldr1 step1 1 log "map should maintain order" - assert $ (1..5) == map identity (1..5) + assert $ (1 .. 5) == map identity (1 .. 5) log "map should be stack-safe" - void $ pure $ map identity (1..100000) + void $ pure $ map identity (1 .. 100000) log "map should be correct" - assert $ (1..1000000) == map (_ + 1) (0..999999) + assert $ (1 .. 1000000) == map (_ + 1) (0 .. 999999) log "transpose" - assert $ transpose (l [l [1,2,3], l[4,5,6], l [7,8,9]]) == - (l [l [1,4,7], l[2,5,8], l [3,6,9]]) + assert $ transpose (l [ l [ 1, 2, 3 ], l [ 4, 5, 6 ], l [ 7, 8, 9 ] ]) == + (l [ l [ 1, 4, 7 ], l [ 2, 5, 8 ], l [ 3, 6, 9 ] ]) log "transpose skips elements when rows don't match" - assert $ transpose ((10:11:Nil) : (20:Nil) : Nil : (30:31:32:Nil) : Nil) == - ((10:20:30:Nil) : (11:31:Nil) : (32:Nil) : Nil) + assert $ transpose ((10 : 11 : Nil) : (20 : Nil) : Nil : (30 : 31 : 32 : Nil) : Nil) == + ((10 : 20 : 30 : Nil) : (11 : 31 : Nil) : (32 : Nil) : Nil) log "transpose Nil == Nil" assert $ transpose Nil == (Nil :: List (List Int)) log "transpose (singleton Nil) == Nil" @@ -402,11 +402,11 @@ testList = do assert $ traverseWithIndex (const Just) xs == Just xs log "traverseWithIndex should be correct" - assert $ traverseWithIndex (\i a -> Just $ i + a) (fromFoldable [2, 2, 2]) - == Just (fromFoldable [2, 3, 4]) + assert $ traverseWithIndex (\i a -> Just $ i + a) (fromFoldable [ 2, 2, 2 ]) + == Just (fromFoldable [ 2, 3, 4 ]) log "append should concatenate two lists" - assert $ (l [1, 2]) <> (l [3, 4]) == (l [1, 2, 3, 4]) + assert $ (l [ 1, 2 ]) <> (l [ 3, 4 ]) == (l [ 1, 2, 3, 4 ]) log "append should be stack-safe" void $ pure $ xs <> xs diff --git a/test/Test/Data/List/Lazy.purs b/test/Test/Data/List/Lazy.purs index c1c2978..328dfa0 100644 --- a/test/Test/Data/List/Lazy.purs +++ b/test/Test/Data/List/Lazy.purs @@ -8,9 +8,9 @@ import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.Function (on) import Data.FunctorWithIndex (mapWithIndex) import Data.Lazy as Z -import Data.List.Lazy (List, Pattern(..), alterAt, catMaybes, concat, concatMap, cycle, cons, delete, deleteAt, deleteBy, drop, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, foldMap, foldl, foldr, foldrLazy, fromFoldable, group, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, iterate, last, length, mapMaybe, modifyAt, nil, nub, nubBy, nubEq, nubByEq, null, partition, range, repeat, replicate, replicateM, reverse, scanlLazy, singleton, slice, snoc, span, stripPrefix, tail, take, takeWhile, transpose, uncons, union, unionBy, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) +import Data.List.Lazy (List, Pattern(..), alterAt, catMaybes, concat, concatMap, cons, cycle, delete, deleteAt, deleteBy, drop, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, foldMap, foldl, foldr, foldrLazy, fromFoldable, group, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, iterate, last, length, mapMaybe, modifyAt, nil, nub, nubBy, nubByEq, nubEq, null, partition, range, repeat, replicate, replicateM, reverse, scanlLazy, singleton, slice, snoc, span, stripPrefix, tail, take, takeWhile, transpose, uncons, union, unionBy, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) import Data.List.Lazy.NonEmpty as NEL -import Data.Maybe (Maybe(..), isNothing, fromJust) +import Data.Maybe (Maybe(..), fromJust, isNothing) import Data.Monoid.Additive (Additive(..)) import Data.NonEmpty ((:|)) import Data.Traversable (traverse) @@ -30,9 +30,9 @@ testListLazy = do nel xxs = NEL.NonEmptyList (Z.defer \_ -> xxs) longList = range 1 100000 log "strip prefix" - assert $ stripPrefix (Pattern (l [1])) (l [1,2]) == Just (l [2]) - assert $ stripPrefix (Pattern (l [])) (l [1]) == Just (l [1]) - assert $ stripPrefix (Pattern (l [2])) (l [1]) == Nothing + assert $ stripPrefix (Pattern (l [ 1 ])) (l [ 1, 2 ]) == Just (l [ 2 ]) + assert $ stripPrefix (Pattern (l [])) (l [ 1 ]) == Just (l [ 1 ]) + assert $ stripPrefix (Pattern (l [ 2 ])) (l [ 1 ]) == Nothing log "append should be stack-safe" assert $ length (longList <> longList) == (2 * length longList) @@ -73,8 +73,8 @@ testListLazy = do void $ pure $ map (foldMapWithIndex (\i _ -> Additive i)) $ NEL.fromFoldable $ range 1 100000 log "foldMapWithIndex should be left-to-right" - assert $ foldMapWithIndex (\i _ -> show i) (fromFoldable [0, 0, 0]) == "012" - assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [0, 0, 0]) == Just "012" + assert $ foldMapWithIndex (\i _ -> show i) (fromFoldable [ 0, 0, 0 ]) == "012" + assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [ 0, 0, 0 ]) == Just "012" log "traverse should be stack-safe" assert $ ((traverse Just longList) >>= last) == last longList @@ -84,35 +84,35 @@ testListLazy = do assert $ traverseWithIndex (const Just) (NEL.fromFoldable longList) == Just (NEL.fromFoldable longList) log "traverseWithIndex should be correct" - assert $ traverseWithIndex (\i a -> Just $ i + a) (fromFoldable [2, 2, 2]) - == Just (fromFoldable [2, 3, 4]) - assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [2, 2, 2]) - == Just (NEL.fromFoldable [2, 3, 4]) + assert $ traverseWithIndex (\i a -> Just $ i + a) (fromFoldable [ 2, 2, 2 ]) + == Just (fromFoldable [ 2, 3, 4 ]) + assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [ 2, 2, 2 ]) + == Just (NEL.fromFoldable [ 2, 3, 4 ]) log "bind should be stack-safe" void $ pure $ last $ longList >>= pure log "singleton should construct an list with a single value" - assert $ singleton 1 == l [1] - assert $ singleton "foo" == l ["foo"] - assert $ singleton nil' == l [l []] + assert $ singleton 1 == l [ 1 ] + assert $ singleton "foo" == l [ "foo" ] + assert $ singleton nil' == l [ l [] ] log "range should create an inclusive list of integers for the specified start and end" - assert $ (range 0 5) == l [0, 1, 2, 3, 4, 5] - assert $ (range 2 (-3)) == l [2, 1, 0, -1, -2, -3] + assert $ (range 0 5) == l [ 0, 1, 2, 3, 4, 5 ] + assert $ (range 2 (-3)) == l [ 2, 1, 0, -1, -2, -3 ] log "range should be lazy" assert $ head (range 0 100000000) == Just 0 log "replicate should produce an list containing an item a specified number of times" - assert $ replicate 3 true == l [true, true, true] - assert $ replicate 1 "foo" == l ["foo"] + assert $ replicate 3 true == l [ true, true, true ] + assert $ replicate 1 "foo" == l [ "foo" ] assert $ replicate 0 "foo" == l [] assert $ replicate (-1) "foo" == l [] log "replicateM should perform the monadic action the correct number of times" - assert $ replicateM 3 (Just 1) == Just (l [1, 1, 1]) - assert $ replicateM 1 (Just 1) == Just (l [1]) + assert $ replicateM 3 (Just 1) == Just (l [ 1, 1, 1 ]) + assert $ replicateM 1 (Just 1) == Just (l [ 1 ]) assert $ replicateM 0 (Just 1) == Just (l []) assert $ replicateM (-1) (Just 1) == Just (l []) @@ -120,8 +120,8 @@ testListLazy = do -- many log "null should return false for non-empty lists" - assert $ null (l [1]) == false - assert $ null (l [1, 2, 3]) == false + assert $ null (l [ 1 ]) == false + assert $ null (l [ 1, 2, 3 ]) == false log "null should return true for an empty list" assert $ null nil' == true @@ -131,45 +131,45 @@ testListLazy = do log "length should return the number of items in an list" assert $ length nil' == 0 - assert $ length (l [1]) == 1 - assert $ length (l [1, 2, 3, 4, 5]) == 5 + assert $ length (l [ 1 ]) == 1 + assert $ length (l [ 1, 2, 3, 4, 5 ]) == 5 log "snoc should add an item to the end of an list" - assert $ l [1, 2, 3] `snoc` 4 == l [1, 2, 3, 4] - assert $ nil' `snoc` 1 == l [1] + assert $ l [ 1, 2, 3 ] `snoc` 4 == l [ 1, 2, 3, 4 ] + assert $ nil' `snoc` 1 == l [ 1 ] log "insert should be stack-safe" assert $ last (insert 100001 longList) == Just 100001 log "insert should add an item at the appropriate place in a sorted list" - assert $ insert 1.5 (l [1.0, 2.0, 3.0]) == l [1.0, 1.5, 2.0, 3.0] - assert $ insert 4 (l [1, 2, 3]) == l [1, 2, 3, 4] - assert $ insert 0 (l [1, 2, 3]) == l [0, 1, 2, 3] + assert $ insert 1.5 (l [ 1.0, 2.0, 3.0 ]) == l [ 1.0, 1.5, 2.0, 3.0 ] + assert $ insert 4 (l [ 1, 2, 3 ]) == l [ 1, 2, 3, 4 ] + assert $ insert 0 (l [ 1, 2, 3 ]) == l [ 0, 1, 2, 3 ] log "insertBy should add an item at the appropriate place in a sorted list using the specified comparison" - assert $ insertBy (flip compare) 4 (l [1, 2, 3]) == l [4, 1, 2, 3] - assert $ insertBy (flip compare) 0 (l [1, 2, 3]) == l [1, 2, 3, 0] + assert $ insertBy (flip compare) 4 (l [ 1, 2, 3 ]) == l [ 4, 1, 2, 3 ] + assert $ insertBy (flip compare) 0 (l [ 1, 2, 3 ]) == l [ 1, 2, 3, 0 ] log "head should return a Just-wrapped first value of a non-empty list" - assert $ head (l ["foo", "bar"]) == Just "foo" + assert $ head (l [ "foo", "bar" ]) == Just "foo" log "head should return Nothing for an empty list" assert $ head nil' == Nothing log "last should return a Just-wrapped last value of a non-empty list" - assert $ last (l ["foo", "bar"]) == Just "bar" + assert $ last (l [ "foo", "bar" ]) == Just "bar" log "last should return Nothing for an empty list" assert $ last nil' == Nothing log "tail should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ tail (l ["foo", "bar", "baz"]) == Just (l ["bar", "baz"]) + assert $ tail (l [ "foo", "bar", "baz" ]) == Just (l [ "bar", "baz" ]) log "tail should return Nothing for an empty list" assert $ tail nil' == Nothing log "init should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ init (l ["foo", "bar", "baz"]) == Just (l ["foo", "bar"]) + assert $ init (l [ "foo", "bar", "baz" ]) == Just (l [ "foo", "bar" ]) log "init should return Nothing for an empty list" assert $ init nil' == Nothing @@ -178,97 +178,97 @@ testListLazy = do assert $ isNothing (uncons nil') log "uncons should split an list into a head and tail record when there is at least one item" - let u1 = uncons (l [1]) + let u1 = uncons (l [ 1 ]) assert $ unsafePartial (fromJust u1).head == 1 - assert $ unsafePartial(fromJust u1).tail == l [] - let u2 = uncons (l [1, 2, 3]) + assert $ unsafePartial (fromJust u1).tail == l [] + let u2 = uncons (l [ 1, 2, 3 ]) assert $ unsafePartial (fromJust u2).head == 1 - assert $ unsafePartial (fromJust u2).tail == l [2, 3] + assert $ unsafePartial (fromJust u2).tail == l [ 2, 3 ] log "(!!) should return Just x when the index is within the bounds of the list" - assert $ l [1, 2, 3] !! 0 == (Just 1) - assert $ l [1, 2, 3] !! 1 == (Just 2) - assert $ l [1, 2, 3] !! 2 == (Just 3) + assert $ l [ 1, 2, 3 ] !! 0 == (Just 1) + assert $ l [ 1, 2, 3 ] !! 1 == (Just 2) + assert $ l [ 1, 2, 3 ] !! 2 == (Just 3) log "(!!) should return Nothing when the index is outside of the bounds of the list" - assert $ l [1, 2, 3] !! 6 == Nothing - assert $ l [1, 2, 3] !! (-1) == Nothing + assert $ l [ 1, 2, 3 ] !! 6 == Nothing + assert $ l [ 1, 2, 3 ] !! (-1) == Nothing log "elemIndex should return the index of an item that a predicate returns true for in an list" - assert $ elemIndex 1 (l [1, 2, 1]) == Just 0 - assert $ elemIndex 4 (l [1, 2, 1]) == Nothing + assert $ elemIndex 1 (l [ 1, 2, 1 ]) == Just 0 + assert $ elemIndex 4 (l [ 1, 2, 1 ]) == Nothing log "elemLastIndex should return the last index of an item in an list" - assert $ elemLastIndex 1 (l [1, 2, 1]) == Just 2 - assert $ elemLastIndex 4 (l [1, 2, 1]) == Nothing + assert $ elemLastIndex 1 (l [ 1, 2, 1 ]) == Just 2 + assert $ elemLastIndex 4 (l [ 1, 2, 1 ]) == Nothing log "findIndex should return the index of an item that a predicate returns true for in an list" - assert $ findIndex (_ /= 1) (l [1, 2, 1]) == Just 1 - assert $ findIndex (_ == 3) (l [1, 2, 1]) == Nothing + assert $ findIndex (_ /= 1) (l [ 1, 2, 1 ]) == Just 1 + assert $ findIndex (_ == 3) (l [ 1, 2, 1 ]) == Nothing log "findIndex should work on huge lists" assert $ findIndex (_ == 3) (range 0 100000000) == Just 3 log "findLastIndex should return the last index of an item in an list" - assert $ findLastIndex (_ /= 1) (l [2, 1, 2]) == Just 2 - assert $ findLastIndex (_ == 3) (l [2, 1, 2]) == Nothing + assert $ findLastIndex (_ /= 1) (l [ 2, 1, 2 ]) == Just 2 + assert $ findLastIndex (_ == 3) (l [ 2, 1, 2 ]) == Nothing log "insertAt should add an item at the specified index" - assert $ (insertAt 0 1 (l [2, 3])) == (l [1, 2, 3]) - assert $ (insertAt 1 1 (l [2, 3])) == (l [2, 1, 3]) - assert $ (insertAt 2 1 (l [2, 3])) == (l [2, 3, 1]) + assert $ (insertAt 0 1 (l [ 2, 3 ])) == (l [ 1, 2, 3 ]) + assert $ (insertAt 1 1 (l [ 2, 3 ])) == (l [ 2, 1, 3 ]) + assert $ (insertAt 2 1 (l [ 2, 3 ])) == (l [ 2, 3, 1 ]) log "deleteAt should remove an item at the specified index" - assert $ (deleteAt 0 (l [1, 2, 3])) == (l [2, 3]) - assert $ (deleteAt 1 (l [1, 2, 3])) == (l [1, 3]) + assert $ (deleteAt 0 (l [ 1, 2, 3 ])) == (l [ 2, 3 ]) + assert $ (deleteAt 1 (l [ 1, 2, 3 ])) == (l [ 1, 3 ]) log "updateAt should replace an item at the specified index" - assert $ (updateAt 0 9 (l [1, 2, 3])) == (l [9, 2, 3]) - assert $ (updateAt 1 9 (l [1, 2, 3])) == (l [1, 9, 3]) + assert $ (updateAt 0 9 (l [ 1, 2, 3 ])) == (l [ 9, 2, 3 ]) + assert $ (updateAt 1 9 (l [ 1, 2, 3 ])) == (l [ 1, 9, 3 ]) log "modifyAt should update an item at the specified index" - assert $ (modifyAt 0 (_ + 1) (l [1, 2, 3])) == (l [2, 2, 3]) - assert $ (modifyAt 1 (_ + 1) (l [1, 2, 3])) == (l [1, 3, 3]) + assert $ (modifyAt 0 (_ + 1) (l [ 1, 2, 3 ])) == (l [ 2, 2, 3 ]) + assert $ (modifyAt 1 (_ + 1) (l [ 1, 2, 3 ])) == (l [ 1, 3, 3 ]) log "alterAt should update an item at the specified index when the function returns Just" - assert $ (alterAt 0 (Just <<< (_ + 1)) (l [1, 2, 3])) == (l [2, 2, 3]) - assert $ (alterAt 1 (Just <<< (_ + 1)) (l [1, 2, 3])) == (l [1, 3, 3]) + assert $ (alterAt 0 (Just <<< (_ + 1)) (l [ 1, 2, 3 ])) == (l [ 2, 2, 3 ]) + assert $ (alterAt 1 (Just <<< (_ + 1)) (l [ 1, 2, 3 ])) == (l [ 1, 3, 3 ]) log "alterAt should drop an item at the specified index when the function returns Nothing" - assert $ (alterAt 0 (const Nothing) (l [1, 2, 3])) == (l [2, 3]) - assert $ (alterAt 1 (const Nothing) (l [1, 2, 3])) == (l [1, 3]) + assert $ (alterAt 0 (const Nothing) (l [ 1, 2, 3 ])) == (l [ 2, 3 ]) + assert $ (alterAt 1 (const Nothing) (l [ 1, 2, 3 ])) == (l [ 1, 3 ]) log "reverse should reverse the order of items in an list" - assert $ (reverse (l [1, 2, 3])) == l [3, 2, 1] + assert $ (reverse (l [ 1, 2, 3 ])) == l [ 3, 2, 1 ] assert $ (reverse nil') == nil' log "reverse should be stack-safe" assert $ head (reverse longList) == last longList log "concat should join an list of lists" - assert $ (concat (l [l [1, 2], l [3, 4]])) == l [1, 2, 3, 4] - assert $ (concat (l [l [1], nil'])) == l [1] - assert $ (concat (l [nil', nil'])) == nil' + assert $ (concat (l [ l [ 1, 2 ], l [ 3, 4 ] ])) == l [ 1, 2, 3, 4 ] + assert $ (concat (l [ l [ 1 ], nil' ])) == l [ 1 ] + assert $ (concat (l [ nil', nil' ])) == nil' log "concatMap should be equivalent to (concat <<< map)" - assert $ concatMap doubleAndOrig (l [1, 2, 3]) == concat (map doubleAndOrig (l [1, 2, 3])) + assert $ concatMap doubleAndOrig (l [ 1, 2, 3 ]) == concat (map doubleAndOrig (l [ 1, 2, 3 ])) log "filter should remove items that don't match a predicate" - assert $ filter odd (range 0 10) == l [1, 3, 5, 7, 9] + assert $ filter odd (range 0 10) == l [ 1, 3, 5, 7, 9 ] log "filterM should remove items that don't match a predicate while using a monadic behaviour" - assert $ filterM (Just <<< odd) (range 0 10) == Just (l [1, 3, 5, 7, 9]) + assert $ filterM (Just <<< odd) (range 0 10) == Just (l [ 1, 3, 5, 7, 9 ]) assert $ filterM (const Nothing) (repeat 0) == Nothing log "mapMaybe should transform every item in an list, throwing out Nothing values" - assert $ mapMaybe (\x -> if x /= 0 then Just x else Nothing) (l [0, 1, 0, 0, 2, 3]) == l [1, 2, 3] + assert $ mapMaybe (\x -> if x /= 0 then Just x else Nothing) (l [ 0, 1, 0, 0, 2, 3 ]) == l [ 1, 2, 3 ] log "catMaybe should take an list of Maybe values and throw out Nothings" - assert $ catMaybes (l [Nothing, Just 2, Nothing, Just 4]) == l [2, 4] + assert $ catMaybes (l [ Nothing, Just 2, Nothing, Just 4 ]) == l [ 2, 4 ] log "mapWithIndex should take a list of values and apply a function which also takes the index into account" - assert $ mapWithIndex (\x ix -> x + ix) (fromFoldable [0, 1, 2, 3]) == fromFoldable [0, 2, 4, 6] - assert $ map (mapWithIndex (\x ix -> x + ix)) (NEL.fromFoldable [0, 1, 2, 3]) == NEL.fromFoldable [0, 2, 4, 6] + assert $ mapWithIndex (\x ix -> x + ix) (fromFoldable [ 0, 1, 2, 3 ]) == fromFoldable [ 0, 2, 4, 6 ] + assert $ map (mapWithIndex (\x ix -> x + ix)) (NEL.fromFoldable [ 0, 1, 2, 3 ]) == NEL.fromFoldable [ 0, 2, 4, 6 ] -- log "sort should reorder a list into ascending order based on the result of compare" -- assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6] @@ -277,164 +277,179 @@ testListLazy = do -- assert $ sortBy (flip compare) (l [1, 3, 2, 5, 6, 4]) == l [6, 5, 4, 3, 2, 1] log "slice should work on infinite lists" - assert $ (slice 3 5 (repeat 0)) == l [0, 0] + assert $ (slice 3 5 (repeat 0)) == l [ 0, 0 ] log "take should keep the specified number of items from the front of an list, discarding the rest" - assert $ (take 1 (l [1, 2, 3])) == l [1] - assert $ (take 2 (l [1, 2, 3])) == l [1, 2] + assert $ (take 1 (l [ 1, 2, 3 ])) == l [ 1 ] + assert $ (take 2 (l [ 1, 2, 3 ])) == l [ 1, 2 ] assert $ (take 1 nil') == nil' log "take should evaluate exactly n items which we needed" - assert let oops x = 0 : oops x - xs = 1 : defer oops - in take 1 xs == l [1] + assert + let + oops x = 0 : oops x + xs = 1 : defer oops + in + take 1 xs == l [ 1 ] -- If `take` evaluate more than once, it would crash with a stack overflow log "takeWhile should keep all values that match a predicate from the front of an list" - assert $ (takeWhile (_ /= 2) (l [1, 2, 3])) == l [1] - assert $ (takeWhile (_ /= 3) (l [1, 2, 3])) == l [1, 2] + assert $ (takeWhile (_ /= 2) (l [ 1, 2, 3 ])) == l [ 1 ] + assert $ (takeWhile (_ /= 3) (l [ 1, 2, 3 ])) == l [ 1, 2 ] assert $ (takeWhile (_ /= 1) nil') == nil' log "takeWhile should work on huge lists" - assert $ (takeWhile (_ /= 3) (range 0 100000000)) == l [0, 1, 2] + assert $ (takeWhile (_ /= 3) (range 0 100000000)) == l [ 0, 1, 2 ] log "drop should remove the specified number of items from the front of an list" - assert $ (drop 1 (l [1, 2, 3])) == l [2, 3] - assert $ (drop 2 (l [1, 2, 3])) == l [3] + assert $ (drop 1 (l [ 1, 2, 3 ])) == l [ 2, 3 ] + assert $ (drop 2 (l [ 1, 2, 3 ])) == l [ 3 ] assert $ (drop 1 nil') == nil' log "dropWhile should remove all values that match a predicate from the front of an list" - assert $ (dropWhile (_ /= 1) (l [1, 2, 3])) == l [1, 2, 3] - assert $ (dropWhile (_ /= 2) (l [1, 2, 3])) == l [2, 3] + assert $ (dropWhile (_ /= 1) (l [ 1, 2, 3 ])) == l [ 1, 2, 3 ] + assert $ (dropWhile (_ /= 2) (l [ 1, 2, 3 ])) == l [ 2, 3 ] assert $ (dropWhile (_ /= 1) nil') == nil' log "span should split an list in two based on a predicate" - let spanResult = span (_ < 4) (l [1, 2, 3, 4, 5, 6, 7]) - assert $ spanResult.init == l [1, 2, 3] - assert $ spanResult.rest == l [4, 5, 6, 7] + let spanResult = span (_ < 4) (l [ 1, 2, 3, 4, 5, 6, 7 ]) + assert $ spanResult.init == l [ 1, 2, 3 ] + 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 [NEL.singleton 1, nel (2 :| l [2]), nel (3 :| l [3, 3]), NEL.singleton 1] + assert $ group (l [ 1, 2, 2, 3, 3, 3, 1 ]) == l [ NEL.singleton 1, nel (2 :| l [ 2 ]), nel (3 :| l [ 3, 3 ]), NEL.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 [nel (1 :| l [1]), NEL.singleton 2, NEL.singleton 2, nel (3 :| l [3])] + assert $ groupBy (\x y -> odd x && odd y) (l [ 1, 1, 2, 2, 3, 3 ]) == l [ nel (1 :| l [ 1 ]), NEL.singleton 2, NEL.singleton 2, nel (3 :| l [ 3 ]) ] log "partition should separate a list into a tuple of lists that do and do not satisfy a predicate" - let partitioned = partition (_ > 2) (l [1, 5, 3, 2, 4]) - assert $ partitioned.yes == l [5, 3, 4] - assert $ partitioned.no == l [1, 2] + let partitioned = partition (_ > 2) (l [ 1, 5, 3, 2, 4 ]) + assert $ partitioned.yes == l [ 5, 3, 4 ] + assert $ partitioned.no == l [ 1, 2 ] log "iterate on nonempty lazy list should apply supplied function correctly" - assert $ (take 3 $ NEL.toList $ NEL.iterate (_ + 1) 0) == l [0, 1, 2] + assert $ (take 3 $ NEL.toList $ NEL.iterate (_ + 1) 0) == l [ 0, 1, 2 ] log "nub should remove duplicate elements from the list, keeping the first occurrence" - assert $ nub (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4] + assert $ nub (l [ 1, 2, 2, 3, 4, 1 ]) == l [ 1, 2, 3, 4 ] log "nub should not consume more of the input list than necessary" - assert $ (take 3 $ nub $ cycle $ l [1,2,3]) == l [1,2,3] + assert $ (take 3 $ nub $ cycle $ l [ 1, 2, 3 ]) == l [ 1, 2, 3 ] log "nubBy should remove duplicate items from the list using a supplied predicate" let nubPred = compare `on` Array.length - assert $ nubBy nubPred (l [[1],[2],[3,4]]) == l [[1],[3,4]] + assert $ nubBy nubPred (l [ [ 1 ], [ 2 ], [ 3, 4 ] ]) == l [ [ 1 ], [ 3, 4 ] ] log "nubEq should remove duplicate elements from the list, keeping the first occurrence" - assert $ nubEq (l [1, 2, 2, 3, 4, 1]) == l [1, 2, 3, 4] + assert $ nubEq (l [ 1, 2, 2, 3, 4, 1 ]) == l [ 1, 2, 3, 4 ] log "nubEq should not consume more of the input list than necessary" - assert $ (take 3 $ nubEq $ cycle $ l [1,2,3]) == l [1,2,3] + assert $ (take 3 $ nubEq $ cycle $ l [ 1, 2, 3 ]) == l [ 1, 2, 3 ] log "nubByEq should remove duplicate items from the list using a supplied predicate" let mod3eq = eq `on` \n -> mod n 3 - assert $ nubByEq mod3eq (l [1, 3, 4, 5, 6]) == l [1, 3, 5] + assert $ nubByEq mod3eq (l [ 1, 3, 4, 5, 6 ]) == l [ 1, 3, 5 ] log "union should produce the union of two lists" - assert $ union (l [1, 2, 3]) (l [2, 3, 4]) == l [1, 2, 3, 4] - assert $ union (l [1, 1, 2, 3]) (l [2, 3, 4]) == l [1, 1, 2, 3, 4] + assert $ union (l [ 1, 2, 3 ]) (l [ 2, 3, 4 ]) == l [ 1, 2, 3, 4 ] + assert $ union (l [ 1, 1, 2, 3 ]) (l [ 2, 3, 4 ]) == l [ 1, 1, 2, 3, 4 ] log "unionBy should produce the union of two lists using the specified equality relation" - assert $ unionBy (\_ y -> y < 5) (l [1, 2, 3]) (l [2, 3, 4, 5, 6]) == l [1, 2, 3, 5, 6] + assert $ unionBy (\_ y -> y < 5) (l [ 1, 2, 3 ]) (l [ 2, 3, 4, 5, 6 ]) == l [ 1, 2, 3, 5, 6 ] log "delete should remove the first matching item from an list" - assert $ delete 1 (l [1, 2, 1]) == l [2, 1] - assert $ delete 2 (l [1, 2, 1]) == l [1, 1] + assert $ delete 1 (l [ 1, 2, 1 ]) == l [ 2, 1 ] + assert $ delete 2 (l [ 1, 2, 1 ]) == l [ 1, 1 ] log "deleteBy should remove the first equality-relation-matching item from an list" - assert $ deleteBy (/=) 2 (l [1, 2, 1]) == l [2, 1] - assert $ deleteBy (/=) 1 (l [1, 2, 1]) == l [1, 1] + assert $ deleteBy (/=) 2 (l [ 1, 2, 1 ]) == l [ 2, 1 ] + assert $ deleteBy (/=) 1 (l [ 1, 2, 1 ]) == l [ 1, 1 ] log "(\\\\) should return the difference between two lists" - assert $ l [1, 2, 3, 4, 3, 2, 1] \\ l [1, 1, 2, 3] == l [4, 3, 2] + assert $ l [ 1, 2, 3, 4, 3, 2, 1 ] \\ l [ 1, 1, 2, 3 ] == l [ 4, 3, 2 ] log "intersect should return the intersection of two lists" - assert $ intersect (l [1, 2, 3, 4, 3, 2, 1]) (l [1, 1, 2, 3]) == l [1, 2, 3, 3, 2, 1] + assert $ intersect (l [ 1, 2, 3, 4, 3, 2, 1 ]) (l [ 1, 1, 2, 3 ]) == l [ 1, 2, 3, 3, 2, 1 ] log "intersectBy should return the intersection of two lists using the specified equivalence relation" - assert $ intersectBy (\x y -> (x * 2) == y) (l [1, 2, 3]) (l [2, 6]) == l [1, 3] + assert $ intersectBy (\x y -> (x * 2) == y) (l [ 1, 2, 3 ]) (l [ 2, 6 ]) == l [ 1, 3 ] log "repeat on non-empty lazy list should repeat element" - assert $ (take 3 $ NEL.toList $ NEL.repeat 0) == l [0, 0, 0] + assert $ (take 3 $ NEL.toList $ NEL.repeat 0) == l [ 0, 0, 0 ] log "zipWith should use the specified function to zip two lists together" - assert $ zipWith (\x y -> l [show x, y]) (l [1, 2, 3]) (l ["a", "b", "c"]) == l [l ["1", "a"], l ["2", "b"], l ["3", "c"]] + assert $ zipWith (\x y -> l [ show x, y ]) (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == l [ l [ "1", "a" ], l [ "2", "b" ], l [ "3", "c" ] ] log "zipWithA should use the specified function to zip two lists together" - assert $ zipWithA (\x y -> Just $ Tuple x y) (l [1, 2, 3]) (l ["a", "b", "c"]) == Just (l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) + assert $ zipWithA (\x y -> Just $ Tuple x y) (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == Just (l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) log "zipWithA should work with infinite lists" assert $ - let inf = repeat 1 - ints = replicate 10 3 - zipped = zipWithA (\x y -> Just (x + y)) inf ints - in map length zipped == pure (length ints) + let + inf = repeat 1 + ints = replicate 10 3 + zipped = zipWithA (\x y -> Just (x + y)) inf ints + in + map length zipped == pure (length ints) log "zip should use the specified function to zip two lists together" - assert $ zip (l [1, 2, 3]) (l ["a", "b", "c"]) == l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] + assert $ zip (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) == l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] log "unzip should deconstruct a list of tuples into a tuple of lists" - assert $ unzip (l [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) == Tuple (l [1, 2, 3]) (l ["a", "b", "c"]) + assert $ unzip (l [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) == Tuple (l [ 1, 2, 3 ]) (l [ "a", "b", "c" ]) log "foldM should perform a fold using a monadic step function" assert $ foldM (\x y -> Just (x + y)) 0 (range 1 10) == Just 55 assert $ foldM (\_ _ -> Nothing) 0 (range 1 10) == Nothing log "foldM should work ok on infinite lists" - assert let infs = iterate (_ + 1) 1 - f acc x = if x >= 10 then Nothing else Just (cons 0 acc) - in foldM f nil infs == Nothing + assert + let + infs = iterate (_ + 1) 1 + f acc x = if x >= 10 then Nothing else Just (cons 0 acc) + in + foldM f nil infs == Nothing log "foldrLazy should work ok on infinite lists" - assert let infs = iterate (_ + 1) 1 - infs' = foldrLazy cons nil infs - in take 1000 infs == take 1000 infs' + assert + let + infs = iterate (_ + 1) 1 + infs' = foldrLazy cons nil infs + in + take 1000 infs == take 1000 infs' log "scanlLazy should work ok on infinite lists" - assert let infs = iterate (_ + 1) 1 - infs' = scanlLazy (\_ i -> i) 0 infs - in take 1000 infs == take 1000 infs' + assert + let + infs = iterate (_ + 1) 1 + infs' = scanlLazy (\_ i -> i) 0 infs + in + take 1000 infs == take 1000 infs' log "scanlLazy folds to the left" - assert $ scanlLazy (+) 5 (1..4) == l [6, 8, 11, 15] + assert $ scanlLazy (+) 5 (1 .. 4) == l [ 6, 8, 11, 15 ] log "can find the first 10 primes using lazy lists" - let eratos :: List Int -> List Int - eratos xs = defer \_ -> - case uncons xs of - Nothing -> nil - Just { head: p, tail: ys } -> p `cons` eratos (filter (\x -> x `mod` p /= 0) ys) + let + eratos :: List Int -> List Int + eratos xs = defer \_ -> + case uncons xs of + Nothing -> nil + Just { head: p, tail: ys } -> p `cons` eratos (filter (\x -> x `mod` p /= 0) ys) - upFrom = iterate (1 + _) + upFrom = iterate (1 + _) - primes = eratos $ upFrom 2 - assert $ take 10 primes == l [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] + primes = eratos $ upFrom 2 + assert $ take 10 primes == l [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ] log "transpose" - assert $ transpose (l [l [1,2,3], l[4,5,6], l [7,8,9]]) == - (l [l [1,4,7], l[2,5,8], l [3,6,9]]) + assert $ transpose (l [ l [ 1, 2, 3 ], l [ 4, 5, 6 ], l [ 7, 8, 9 ] ]) == + (l [ l [ 1, 4, 7 ], l [ 2, 5, 8 ], l [ 3, 6, 9 ] ]) log "transpose skips elements when rows don't match" - assert $ transpose ((10:11:nil) : (20:nil) : nil : (30:31:32:nil) : nil) == - ((10:20:30:nil) : (11:31:nil) : (32:nil) : nil) + assert $ transpose ((10 : 11 : nil) : (20 : nil) : nil : (30 : 31 : 32 : nil) : nil) == + ((10 : 20 : 30 : nil) : (11 : 31 : nil) : (32 : nil) : nil) log "transpose nil == nil" assert $ transpose nil == (nil :: List (List Int)) @@ -442,22 +457,22 @@ testListLazy = do assert $ transpose (singleton nil) == (nil :: List (List Int)) log "NonEmptyList cons should add an element" - assert $ NEL.toList (NEL.cons 0 (NEL.singleton 1)) == fromFoldable [0, 1] + assert $ NEL.toList (NEL.cons 0 (NEL.singleton 1)) == fromFoldable [ 0, 1 ] log "unfoldr should maintain order" - assert $ (1..5) == unfoldr step 1 + assert $ (1 .. 5) == unfoldr step 1 log "unfoldr1 should maintain order" - assert $ (1..5) == unfoldr1 step1 1 + assert $ (1 .. 5) == unfoldr1 step1 1 log "map should maintain order" - assert $ (1..5) == map identity (1..5) + assert $ (1 .. 5) == map identity (1 .. 5) log "unfoldable replicate1 should be stack-safe for NEL" void $ pure $ NEL.length $ (replicate1 100000 1 :: NEL.NonEmptyList Int) log "unfoldr1 should maintain order for NEL" - assert $ (nel (1 :| l [2, 3, 4, 5])) == unfoldr1 step1 1 + assert $ (nel (1 :| l [ 2, 3, 4, 5 ])) == unfoldr1 step1 1 step :: Int -> Maybe (Tuple Int Int) step 6 = Nothing diff --git a/test/Test/Data/List/NonEmpty.purs b/test/Test/Data/List/NonEmpty.purs index 6ad71c1..d33f76b 100644 --- a/test/Test/Data/List/NonEmpty.purs +++ b/test/Test/Data/List/NonEmpty.purs @@ -4,7 +4,7 @@ import Prelude import Data.Array as Array import Data.Foldable (class Foldable, foldM, foldMap, foldl, length) -import Data.FoldableWithIndex (foldlWithIndex, foldrWithIndex, foldMapWithIndex) +import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.Function (on) import Data.List as L import Data.List.NonEmpty as NEL @@ -23,6 +23,7 @@ testNonEmptyList = do let nel :: forall f a. Foldable f => a -> f a -> NEL.NonEmptyList a nel x xs = NEL.NonEmptyList $ x :| L.fromFoldable xs + l :: forall f a. Foldable f => f a -> L.List a l = L.fromFoldable @@ -32,194 +33,194 @@ testNonEmptyList = do log "length should return the number of items in a non-empty list" assert $ length (nel 1 []) == 1 - assert $ length (nel 1 [2, 3, 4, 5]) == 5 + assert $ length (nel 1 [ 2, 3, 4, 5 ]) == 5 log "length should be stack-safe" void $ pure $ NEL.length $ nel 0 (L.range 1 100000) log "snoc should add an item to the end of a non-empty list" - assert $ nel 1 [2, 3] `NEL.snoc` 4 == nel 1 [2, 3, 4] + assert $ nel 1 [ 2, 3 ] `NEL.snoc` 4 == nel 1 [ 2, 3, 4 ] log "head should return a first value of a non-empty list" - assert $ NEL.head (nel "foo" ["bar"]) == "foo" + assert $ NEL.head (nel "foo" [ "bar" ]) == "foo" log "last should return a last value of a non-empty list" - assert $ NEL.last (nel "foo" ["bar"]) == "bar" + assert $ NEL.last (nel "foo" [ "bar" ]) == "bar" log "tail should return a list containing all the items in a non-empty list apart from the first" - assert $ NEL.tail (nel "foo" ["bar", "baz"]) == (l ["bar", "baz"]) + assert $ NEL.tail (nel "foo" [ "bar", "baz" ]) == (l [ "bar", "baz" ]) log "init should return a list containing all the items in a non-empty list apart from the last" - assert $ NEL.init (nel "foo" ["bar", "baz"]) == (l ["foo", "bar"]) + assert $ NEL.init (nel "foo" [ "bar", "baz" ]) == (l [ "foo", "bar" ]) log "uncons should split a non-empty list into a head and tail record when there is at least one item" let u1 = NEL.uncons (nel 1 []) assert $ u1.head == 1 assert $ u1.tail == l [] - let u2 = NEL.uncons (nel 1 [2, 3]) + let u2 = NEL.uncons (nel 1 [ 2, 3 ]) assert $ u2.head == 1 - assert $ u2.tail == l [2, 3] + assert $ u2.tail == l [ 2, 3 ] log "unsnoc should split a non-empty list into an init and last record when there is at least one item" let v1 = NEL.unsnoc (nel 1 []) assert $ v1.init == l [] assert $ v1.last == 1 - let v2 = NEL.unsnoc (nel 1 [2, 3]) - assert $ v2.init == l [1, 2] + let v2 = NEL.unsnoc (nel 1 [ 2, 3 ]) + assert $ v2.init == l [ 1, 2 ] assert $ v2.last == 3 log "(!!) should return Just x when the index is within the bounds of the non-empty list" - assert $ nel 1 [2, 3] NEL.!! 0 == (Just 1) - assert $ nel 1 [2, 3] NEL.!! 1 == (Just 2) - assert $ nel 1 [2, 3] NEL.!! 2 == (Just 3) + assert $ nel 1 [ 2, 3 ] NEL.!! 0 == (Just 1) + assert $ nel 1 [ 2, 3 ] NEL.!! 1 == (Just 2) + assert $ nel 1 [ 2, 3 ] NEL.!! 2 == (Just 3) log "(!!) should return Nothing when the index is outside of the bounds of the non-empty list" - assert $ nel 1 [2, 3] NEL.!! 6 == Nothing - assert $ nel 1 [2, 3] NEL.!! (-1) == Nothing + assert $ nel 1 [ 2, 3 ] NEL.!! 6 == Nothing + assert $ nel 1 [ 2, 3 ] NEL.!! (-1) == Nothing log "elemIndex should return the index of an item that a predicate returns true for in a non-empty list" - assert $ NEL.elemIndex 1 (nel 1 [2, 1]) == Just 0 - assert $ NEL.elemIndex 4 (nel 1 [2, 1]) == Nothing + assert $ NEL.elemIndex 1 (nel 1 [ 2, 1 ]) == Just 0 + assert $ NEL.elemIndex 4 (nel 1 [ 2, 1 ]) == Nothing log "elemLastIndex should return the last index of an item in a non-empty list" - assert $ NEL.elemLastIndex 1 (nel 1 [2, 1]) == Just 2 - assert $ NEL.elemLastIndex 4 (nel 1 [2, 1]) == Nothing + assert $ NEL.elemLastIndex 1 (nel 1 [ 2, 1 ]) == Just 2 + assert $ NEL.elemLastIndex 4 (nel 1 [ 2, 1 ]) == Nothing log "findIndex should return the index of an item that a predicate returns true for in a non-empty list" - assert $ NEL.findIndex (_ /= 1) (nel 1 [2, 1]) == Just 1 - assert $ NEL.findIndex (_ == 3) (nel 1 [2, 1]) == Nothing + assert $ NEL.findIndex (_ /= 1) (nel 1 [ 2, 1 ]) == Just 1 + assert $ NEL.findIndex (_ == 3) (nel 1 [ 2, 1 ]) == Nothing log "findLastIndex should return the last index of an item in a non-empty list" - assert $ NEL.findLastIndex (_ /= 1) (nel 2 [1, 2]) == Just 2 - assert $ NEL.findLastIndex (_ == 3) (nel 2 [1, 2]) == Nothing + assert $ NEL.findLastIndex (_ /= 1) (nel 2 [ 1, 2 ]) == Just 2 + assert $ NEL.findLastIndex (_ == 3) (nel 2 [ 1, 2 ]) == Nothing log "insertAt should add an item at the specified index" - assert $ (NEL.insertAt 0 1 (nel 2 [3])) == Just (nel 1 [2, 3]) - assert $ (NEL.insertAt 1 1 (nel 2 [3])) == Just (nel 2 [1, 3]) - assert $ (NEL.insertAt 2 1 (nel 2 [3])) == Just (nel 2 [3, 1]) + assert $ (NEL.insertAt 0 1 (nel 2 [ 3 ])) == Just (nel 1 [ 2, 3 ]) + assert $ (NEL.insertAt 1 1 (nel 2 [ 3 ])) == Just (nel 2 [ 1, 3 ]) + assert $ (NEL.insertAt 2 1 (nel 2 [ 3 ])) == Just (nel 2 [ 3, 1 ]) log "insertAt should return Nothing if the index is out of range" assert $ (NEL.insertAt 2 1 (nel 0 [])) == Nothing log "updateAt should replace an item at the specified index" - assert $ (NEL.updateAt 0 9 (nel 1 [2, 3])) == Just (nel 9 [2, 3]) - assert $ (NEL.updateAt 1 9 (nel 1 [2, 3])) == Just (nel 1 [9, 3]) + assert $ (NEL.updateAt 0 9 (nel 1 [ 2, 3 ])) == Just (nel 9 [ 2, 3 ]) + assert $ (NEL.updateAt 1 9 (nel 1 [ 2, 3 ])) == Just (nel 1 [ 9, 3 ]) log "updateAt should return Nothing if the index is out of range" assert $ (NEL.updateAt 1 9 (nel 0 [])) == Nothing log "modifyAt should update an item at the specified index" - assert $ (NEL.modifyAt 0 (_ + 1) (nel 1 [2, 3])) == Just (nel 2 [2, 3]) - assert $ (NEL.modifyAt 1 (_ + 1) (nel 1 [2, 3])) == Just (nel 1 [3, 3]) + assert $ (NEL.modifyAt 0 (_ + 1) (nel 1 [ 2, 3 ])) == Just (nel 2 [ 2, 3 ]) + assert $ (NEL.modifyAt 1 (_ + 1) (nel 1 [ 2, 3 ])) == Just (nel 1 [ 3, 3 ]) log "modifyAt should return Nothing if the index is out of range" assert $ (NEL.modifyAt 1 (_ + 1) (nel 0 [])) == Nothing log "reverse should reverse the order of items in an list" - assert $ (NEL.reverse (nel 1 [2, 3])) == nel 3 [2, 1] + assert $ (NEL.reverse (nel 1 [ 2, 3 ])) == nel 3 [ 2, 1 ] log "concat should join an list of lists" - assert $ (NEL.concat (nel (nel 1 [2]) [nel 3 [4]])) == nel 1 [2, 3, 4] + assert $ (NEL.concat (nel (nel 1 [ 2 ]) [ nel 3 [ 4 ] ])) == nel 1 [ 2, 3, 4 ] log "concatMap should be equivalent to (concat <<< map)" - assert $ NEL.concatMap doubleAndOrig (nel 1 [2, 3]) == NEL.concat (map doubleAndOrig (nel 1 [2, 3])) + assert $ NEL.concatMap doubleAndOrig (nel 1 [ 2, 3 ]) == NEL.concat (map doubleAndOrig (nel 1 [ 2, 3 ])) log "filter should remove items that don't match a predicate" - assert $ NEL.filter odd (nel 0 (L.range 1 10)) == l [1, 3, 5, 7, 9] + assert $ NEL.filter odd (nel 0 (L.range 1 10)) == l [ 1, 3, 5, 7, 9 ] log "filterM should remove items that don't match a predicate while using a monadic behaviour" - assert $ NEL.filterM (Just <<< odd) (nel 0 (L.range 1 10)) == Just (l [1, 3, 5, 7, 9]) + assert $ NEL.filterM (Just <<< odd) (nel 0 (L.range 1 10)) == Just (l [ 1, 3, 5, 7, 9 ]) assert $ NEL.filterM (const Nothing) (nel 0 (L.range 1 10)) == Nothing log "mapMaybe should transform every item in an list, throwing out Nothing values" - assert $ NEL.mapMaybe (\x -> if x /= 0 then Just x else Nothing) (nel 0 [1, 0, 0, 2, 3]) == l [1, 2, 3] + assert $ NEL.mapMaybe (\x -> if x /= 0 then Just x else Nothing) (nel 0 [ 1, 0, 0, 2, 3 ]) == l [ 1, 2, 3 ] log "catMaybe should take an list of Maybe values and throw out Nothings" - assert $ NEL.catMaybes (nel Nothing [Just 2, Nothing, Just 4]) == l [2, 4] + assert $ NEL.catMaybes (nel Nothing [ Just 2, Nothing, Just 4 ]) == l [ 2, 4 ] log "sort should reorder a non-empty list into ascending order based on the result of compare" - assert $ NEL.sort (nel 1 [3, 2, 5, 6, 4]) == nel 1 [2, 3, 4, 5, 6] + assert $ NEL.sort (nel 1 [ 3, 2, 5, 6, 4 ]) == nel 1 [ 2, 3, 4, 5, 6 ] log "sortBy should reorder a non-empty list into ascending order based on the result of a comparison function" - assert $ NEL.sortBy (flip compare) (nel 1 [3, 2, 5, 6, 4]) == nel 6 [5, 4, 3, 2, 1] + assert $ NEL.sortBy (flip compare) (nel 1 [ 3, 2, 5, 6, 4 ]) == nel 6 [ 5, 4, 3, 2, 1 ] log "take should keep the specified number of items from the front of an list, discarding the rest" - assert $ (NEL.take 1 (nel 1 [2, 3])) == l [1] - assert $ (NEL.take 2 (nel 1 [2, 3])) == l [1, 2] + assert $ (NEL.take 1 (nel 1 [ 2, 3 ])) == l [ 1 ] + assert $ (NEL.take 2 (nel 1 [ 2, 3 ])) == l [ 1, 2 ] log "takeWhile should keep all values that match a predicate from the front of an list" - assert $ (NEL.takeWhile (_ /= 2) (nel 1 [2, 3])) == l [1] - assert $ (NEL.takeWhile (_ /= 3) (nel 1 [2, 3])) == l [1, 2] + assert $ (NEL.takeWhile (_ /= 2) (nel 1 [ 2, 3 ])) == l [ 1 ] + assert $ (NEL.takeWhile (_ /= 3) (nel 1 [ 2, 3 ])) == l [ 1, 2 ] log "drop should remove the specified number of items from the front of an list" - assert $ (NEL.drop 1 (nel 1 [2, 3])) == l [2, 3] - assert $ (NEL.drop 2 (nel 1 [2, 3])) == l [3] + assert $ (NEL.drop 1 (nel 1 [ 2, 3 ])) == l [ 2, 3 ] + assert $ (NEL.drop 2 (nel 1 [ 2, 3 ])) == l [ 3 ] log "dropWhile should remove all values that match a predicate from the front of an list" - assert $ (NEL.dropWhile (_ /= 1) (nel 1 [2, 3])) == l [1, 2, 3] - assert $ (NEL.dropWhile (_ /= 2) (nel 1 [2, 3])) == l [2, 3] + assert $ (NEL.dropWhile (_ /= 1) (nel 1 [ 2, 3 ])) == l [ 1, 2, 3 ] + assert $ (NEL.dropWhile (_ /= 2) (nel 1 [ 2, 3 ])) == l [ 2, 3 ] log "span should split an list in two based on a predicate" - let spanResult = NEL.span (_ < 4) (nel 1 [2, 3, 4, 5, 6, 7]) - assert $ spanResult.init == l [1, 2, 3] - assert $ spanResult.rest == l [4, 5, 6, 7] + let spanResult = NEL.span (_ < 4) (nel 1 [ 2, 3, 4, 5, 6, 7 ]) + assert $ spanResult.init == l [ 1, 2, 3 ] + assert $ spanResult.rest == l [ 4, 5, 6, 7 ] log "group should group consecutive equal elements into lists" - assert $ NEL.group (nel 1 [2, 2, 3, 3, 3, 1]) == nel (nel 1 []) [nel 2 [2], nel 3 [3, 3], nel 1 []] + assert $ NEL.group (nel 1 [ 2, 2, 3, 3, 3, 1 ]) == nel (nel 1 []) [ nel 2 [ 2 ], nel 3 [ 3, 3 ], nel 1 [] ] log "groupAll should group equal elements into lists" - assert $ NEL.groupAll (nel 1 [2, 2, 3, 3, 3, 1]) == nel (nel 1 [1]) [nel 2 [2], nel 3 [3, 3]] + assert $ NEL.groupAll (nel 1 [ 2, 2, 3, 3, 3, 1 ]) == nel (nel 1 [ 1 ]) [ nel 2 [ 2 ], nel 3 [ 3, 3 ] ] log "groupBy should group consecutive equal elements into lists based on an equivalence relation" - assert $ NEL.groupBy (\x y -> odd x && odd y) (nel 1 [1, 2, 2, 3, 3]) == nel (nel 1 [1]) [nel 2 [], nel 2 [], nel 3 [3]] + assert $ NEL.groupBy (\x y -> odd x && odd y) (nel 1 [ 1, 2, 2, 3, 3 ]) == nel (nel 1 [ 1 ]) [ nel 2 [], nel 2 [], nel 3 [ 3 ] ] log "groupAllBy should sort then group equal elements into lists based on a comparison function" - assert $ NEL.groupAllBy (compare `on` (_ `div` 10)) (nel 32 [31, 21, 22, 11, 33]) == nel (nel 11 []) [nel 21 [22], nel 32 [31, 33]] + assert $ NEL.groupAllBy (compare `on` (_ `div` 10)) (nel 32 [ 31, 21, 22, 11, 33 ]) == nel (nel 11 []) [ nel 21 [ 22 ], nel 32 [ 31, 33 ] ] log "partition should separate a list into a tuple of lists that do and do not satisfy a predicate" - let partitioned = NEL.partition (_ > 2) (nel 1 [5, 3, 2, 4]) - assert $ partitioned.yes == l [5, 3, 4] - assert $ partitioned.no == l [1, 2] + let partitioned = NEL.partition (_ > 2) (nel 1 [ 5, 3, 2, 4 ]) + assert $ partitioned.yes == l [ 5, 3, 4 ] + assert $ partitioned.no == l [ 1, 2 ] log "nub should remove duplicate elements from the list, keeping the first occurrence" - assert $ NEL.nub (nel 1 [2, 2, 3, 4, 1]) == nel 1 [2, 3, 4] + assert $ NEL.nub (nel 1 [ 2, 2, 3, 4, 1 ]) == nel 1 [ 2, 3, 4 ] log "nubBy should remove duplicate items from the list using a supplied predicate" let nubPred = compare `on` Array.length - assert $ NEL.nubBy nubPred (nel [1] [[2],[3,4]]) == nel [1] [[3,4]] + assert $ NEL.nubBy nubPred (nel [ 1 ] [ [ 2 ], [ 3, 4 ] ]) == nel [ 1 ] [ [ 3, 4 ] ] log "nubEq should remove duplicate elements from the list, keeping the first occurrence" - assert $ NEL.nubEq (nel 1 [2, 2, 3, 4, 1]) == nel 1 [2, 3, 4] + assert $ NEL.nubEq (nel 1 [ 2, 2, 3, 4, 1 ]) == nel 1 [ 2, 3, 4 ] log "nubByEq should remove duplicate items from the list using a supplied predicate" let mod3eq = eq `on` \n -> mod n 3 - assert $ NEL.nubByEq mod3eq (nel 1 [3, 4, 5, 6]) == nel 1 [3, 5] + assert $ NEL.nubByEq mod3eq (nel 1 [ 3, 4, 5, 6 ]) == nel 1 [ 3, 5 ] log "union should produce the union of two lists" - assert $ NEL.union (nel 1 [2, 3]) (nel 2 [3, 4]) == nel 1 [2, 3, 4] - assert $ NEL.union (nel 1 [1, 2, 3]) (nel 2 [3, 4]) == nel 1 [1, 2, 3, 4] + assert $ NEL.union (nel 1 [ 2, 3 ]) (nel 2 [ 3, 4 ]) == nel 1 [ 2, 3, 4 ] + assert $ NEL.union (nel 1 [ 1, 2, 3 ]) (nel 2 [ 3, 4 ]) == nel 1 [ 1, 2, 3, 4 ] log "unionBy should produce the union of two lists using the specified equality relation" - assert $ NEL.unionBy (\_ y -> y < 5) (nel 1 [2, 3]) (nel 2 [3, 4, 5, 6]) == nel 1 [2, 3, 5, 6] + assert $ NEL.unionBy (\_ y -> y < 5) (nel 1 [ 2, 3 ]) (nel 2 [ 3, 4, 5, 6 ]) == nel 1 [ 2, 3, 5, 6 ] log "intersect should return the intersection of two lists" - assert $ NEL.intersect (nel 1 [2, 3, 4, 3, 2, 1]) (nel 1 [1, 2, 3]) == nel 1 [2, 3, 3, 2, 1] + assert $ NEL.intersect (nel 1 [ 2, 3, 4, 3, 2, 1 ]) (nel 1 [ 1, 2, 3 ]) == nel 1 [ 2, 3, 3, 2, 1 ] log "intersectBy should return the intersection of two lists using the specified equivalence relation" - assert $ NEL.intersectBy (\x y -> (x * 2) == y) (nel 1 [2, 3]) (nel 2 [6]) == nel 1 [3] + assert $ NEL.intersectBy (\x y -> (x * 2) == y) (nel 1 [ 2, 3 ]) (nel 2 [ 6 ]) == nel 1 [ 3 ] log "zipWith should use the specified function to zip two lists together" - assert $ NEL.zipWith (\x y -> nel (show x) [y]) (nel 1 [2, 3]) (nel "a" ["b", "c"]) == nel (nel "1" ["a"]) [nel "2" ["b"], nel "3" ["c"]] + assert $ NEL.zipWith (\x y -> nel (show x) [ y ]) (nel 1 [ 2, 3 ]) (nel "a" [ "b", "c" ]) == nel (nel "1" [ "a" ]) [ nel "2" [ "b" ], nel "3" [ "c" ] ] log "zipWithA should use the specified function to zip two lists together" - assert $ NEL.zipWithA (\x y -> Just $ Tuple x y) (nel 1 [2, 3]) (nel "a" ["b", "c"]) == Just (nel (Tuple 1 "a") [Tuple 2 "b", Tuple 3 "c"]) + assert $ NEL.zipWithA (\x y -> Just $ Tuple x y) (nel 1 [ 2, 3 ]) (nel "a" [ "b", "c" ]) == Just (nel (Tuple 1 "a") [ Tuple 2 "b", Tuple 3 "c" ]) log "zip should use the specified function to zip two lists together" - assert $ NEL.zip (nel 1 [2, 3]) (nel "a" ["b", "c"]) == nel (Tuple 1 "a") [Tuple 2 "b", Tuple 3 "c"] + assert $ NEL.zip (nel 1 [ 2, 3 ]) (nel "a" [ "b", "c" ]) == nel (Tuple 1 "a") [ Tuple 2 "b", Tuple 3 "c" ] log "unzip should deconstruct a list of tuples into a tuple of lists" - log $ show $ NEL.unzip (nel (Tuple 1 "a") [Tuple 2 "b", Tuple 3 "c"]) - assert $ NEL.unzip (nel (Tuple 1 "a") [Tuple 2 "b", Tuple 3 "c"]) == Tuple (nel 1 [2, 3]) (nel "a" ["b", "c"]) + log $ show $ NEL.unzip (nel (Tuple 1 "a") [ Tuple 2 "b", Tuple 3 "c" ]) + assert $ NEL.unzip (nel (Tuple 1 "a") [ Tuple 2 "b", Tuple 3 "c" ]) == Tuple (nel 1 [ 2, 3 ]) (nel "a" [ "b", "c" ]) log "foldM should perform a fold using a monadic step function" assert $ foldM (\x y -> Just (x + y)) 0 (nel 1 (L.range 2 10)) == Just 55 @@ -241,11 +242,11 @@ testNonEmptyList = do assert $ NEL.traverse1 Just xs == Just xs log "traverse1 should preserve order" - let ts = nel 0 [1, 2, 3, 4, 5] + let ts = nel 0 [ 1, 2, 3, 4, 5 ] assert $ NEL.traverse1 Just ts == Just ts log "append should concatenate two lists" - assert $ (nel 1 [2]) <> (nel 3 [4]) == (nel 1 [2, 3, 4]) + assert $ (nel 1 [ 2 ]) <> (nel 3 [ 4 ]) == (nel 1 [ 2, 3, 4 ]) log "append should be stack-safe" void $ pure $ xs <> xs @@ -266,20 +267,20 @@ testNonEmptyList = do void $ pure $ map (foldMapWithIndex (\i _ -> Additive i)) $ NEL.fromFoldable $ L.range 1 100000 log "foldMapWithIndex should be left-to-right" - assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [0, 0, 0]) == Just "012" + assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [ 0, 0, 0 ]) == Just "012" log "traverseWithIndex should be stack-safe" assert $ map (traverseWithIndex (const Just)) (NEL.fromFoldable xs) == Just (NEL.fromFoldable xs) log "traverseWithIndex should be correct" - assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [2, 2, 2]) - == Just (NEL.fromFoldable [2, 3, 4]) + assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [ 2, 2, 2 ]) + == Just (NEL.fromFoldable [ 2, 3, 4 ]) log "unfoldable replicate1 should be stack-safe" void $ pure $ NEL.length $ (replicate1 100000 1 :: NEL.NonEmptyList Int) log "unfoldr1 should maintain order" - assert $ (nel 1 [2, 3, 4, 5]) == unfoldr1 step1 1 + assert $ (nel 1 [ 2, 3, 4, 5 ]) == unfoldr1 step1 1 step1 :: Int -> Tuple Int (Maybe Int) step1 n = Tuple n (if n >= 5 then Nothing else Just (n + 1)) diff --git a/test/Test/Data/List/Partial.purs b/test/Test/Data/List/Partial.purs index cf5ea69..619c058 100644 --- a/test/Test/Data/List/Partial.purs +++ b/test/Test/Data/List/Partial.purs @@ -2,14 +2,11 @@ module Test.Data.List.Partial (testListPartial) where import Prelude +import Data.List (List(..), fromFoldable) +import Data.List.Partial (head, init, last, tail) import Effect (Effect) import Effect.Console (log) - -import Data.List (List(..), fromFoldable) -import Data.List.Partial (init, tail, last, head) - import Partial.Unsafe (unsafePartial) - import Test.Assert (assert, assertThrows) testListPartial :: Effect Unit @@ -17,25 +14,25 @@ testListPartial = do let l = fromFoldable log "head should return a Just-wrapped first value of a non-empty list" - assert $ unsafePartial $ head (l ["foo", "bar"]) == "foo" + assert $ unsafePartial $ head (l [ "foo", "bar" ]) == "foo" log "head should throw an error for an empty list" assertThrows \_ -> unsafePartial $ head Nil log "last should return a Just-wrapped last value of a non-empty list" - assert $ unsafePartial $ last (l ["foo", "bar"]) == "bar" + assert $ unsafePartial $ last (l [ "foo", "bar" ]) == "bar" log "last should throw an error for an empty list" assertThrows \_ -> unsafePartial $ last Nil log "tail should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ unsafePartial $ tail (l ["foo", "bar", "baz"]) == l ["bar", "baz"] + assert $ unsafePartial $ tail (l [ "foo", "bar", "baz" ]) == l [ "bar", "baz" ] log "tail should throw an error for an empty list" assertThrows \_ -> unsafePartial $ tail Nil log "init should return a Just-wrapped list containing all the items in an list apart from the first for a non-empty list" - assert $ unsafePartial $ init (l ["foo", "bar", "baz"]) == l ["foo", "bar"] + assert $ unsafePartial $ init (l [ "foo", "bar", "baz" ]) == l [ "foo", "bar" ] log "init should throw an error for an empty list" assertThrows \_ -> unsafePartial $ init Nil diff --git a/test/Test/Data/List/ZipList.purs b/test/Test/Data/List/ZipList.purs index 366c53c..02460bb 100644 --- a/test/Test/Data/List/ZipList.purs +++ b/test/Test/Data/List/ZipList.purs @@ -2,21 +2,19 @@ module Test.Data.List.ZipList (testZipList) where import Prelude -import Effect (Effect) -import Effect.Console (log) - import Data.Array as Array import Data.List.Lazy as LazyList import Data.List.ZipList (ZipList(..)) - +import Effect (Effect) +import Effect.Console (log) import Test.Assert (assert) testZipList :: Effect Unit testZipList = do log "ZipList Applicative instance should be zippy" - testZipWith (+) [1,2,3] [4,5,6] - testZipWith (*) [1,2,3] [4,5,6] - testZipWith const [1,2,3] [4,5,6] + testZipWith (+) [ 1, 2, 3 ] [ 4, 5, 6 ] + testZipWith (*) [ 1, 2, 3 ] [ 4, 5, 6 ] + testZipWith const [ 1, 2, 3 ] [ 4, 5, 6 ] testZipWith :: forall a b c. Eq c => (a -> b -> c) -> Array a -> Array b -> Effect Unit testZipWith f xs ys = diff --git a/test/Test/Main.purs b/test/Test/Main.purs index 096e807..20a9f1e 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -3,12 +3,11 @@ module Test.Main where import Prelude import Effect (Effect) - import Test.Data.List (testList) import Test.Data.List.Lazy (testListLazy) +import Test.Data.List.NonEmpty (testNonEmptyList) import Test.Data.List.Partial (testListPartial) import Test.Data.List.ZipList (testZipList) -import Test.Data.List.NonEmpty (testNonEmptyList) main :: Effect Unit main = do