From 5c7c5e17fbc7c7a31602f2abcc59efb3a3ebba4f Mon Sep 17 00:00:00 2001 From: Yura Lazarev Date: Sun, 14 Jun 2026 23:25:41 +0200 Subject: [PATCH] chore: add treefmt formatting (nix fmt) and format the tree Wire treefmt via treefmt-nix: nixfmt, dhall format, purs-tidy (.tidyrc.json) and LuaFormatter for the FFI (.lua-format, kept over StyLua because it preserves the parentheses pslua's parser needs). `nix fmt` formats; the dev shell installs a content-based pre-commit hook and CI runs `nix fmt && git diff --exit-code` (content-based, since the in-place formatters bump mtime and would trip treefmt --fail-on-change). Lua lines budget 130 cols, matching the raised `luacheck --max-line-length`. The bulk of the diff is the first format pass. --- .github/workflows/ci.yml | 5 +- .gitignore | 2 + .lua-format | 10 + .tidyrc.json | 10 + AGENTS.md | 16 +- bench/Data/Array.purs | 7 +- flake.lock | 23 +- flake.nix | 43 +- src/Data/Array.lua | 12 +- src/Data/Array.purs | 30 +- src/Data/Array/NonEmpty.purs | 100 +++-- src/Data/Array/NonEmpty/Internal.purs | 9 +- src/Data/Array/ST.purs | 6 +- src/Data/Array/ST/Iterator.purs | 3 +- test/Test/Data/Array.purs | 518 ++++++++++++---------- test/Test/Data/Array/NonEmpty.purs | 605 ++++++++++++++++---------- test/Test/Data/Array/Partial.purs | 12 +- test/Test/Data/Array/ST.purs | 516 +++++++++++++--------- test/Test/Data/Array/ST/Partial.purs | 6 +- test/Test/Data/UndefinedOr.purs | 14 +- test/regression/array_st.lua | 97 +++-- treefmt.nix | 43 ++ 22 files changed, 1321 insertions(+), 766 deletions(-) create mode 100644 .lua-format create mode 100644 .tidyrc.json create mode 100644 treefmt.nix diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d624d2e5..4dc2d200 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,4 +24,7 @@ jobs: run: if [ -f scripts/test ]; then nix develop -c bash ./scripts/test; fi - name: Luacheck - run: nix develop -c luacheck --quiet --std lua51 --no-unused-args src/ + run: nix develop -c luacheck --quiet --std lua51 --no-unused-args --max-line-length 130 src/ + + - name: Format check + run: nix fmt && git diff --exit-code diff --git a/.gitignore b/.gitignore index db67e9ad..e0705282 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /.* !/.gitignore !/.github/ +!/.tidyrc.json +!/.lua-format /output/ diff --git a/.lua-format b/.lua-format new file mode 100644 index 00000000..2945014e --- /dev/null +++ b/.lua-format @@ -0,0 +1,10 @@ +# LuaFormatter config for the hand-written FFI under src/. +# 2-space indent. Keep simple functions on one line; column_limit sits a few +# columns under luacheck's 130 limit because lua-format under-counts the leading +# indent and trailing comma, so this keeps every emitted line within 130. +indent_width: 2 +use_tab: false +column_limit: 126 +continuation_indent_width: 2 +keep_simple_function_one_line: true +keep_simple_control_block_one_line: true diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 00000000..8636af8f --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "source", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "first", + "unicode": "source", + "width": 80 +} diff --git a/AGENTS.md b/AGENTS.md index 12c3f5f1..c682f215 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,11 +4,21 @@ A PureScript→Lua FFI fork in the [`purescript-lua`](https://github.com/purescr ## Commands -All commands run inside the nix dev shell: - - Build: `nix develop -c ./scripts/build` - Test: `nix develop -c bash ./scripts/test` (only forks that ship Lua regression tests have one) -- Lint: `nix develop -c luacheck --quiet --std lua51 --no-unused-args src/` +- Lint: `nix develop -c luacheck --quiet --std lua51 --no-unused-args --max-line-length 130 src/` +- Format: `nix fmt` (check: `nix fmt && git diff --exit-code`) + +## Formatting + +`nix fmt` runs treefmt (`treefmt.nix`): nixfmt for Nix, `dhall format`, purs-tidy +for `*.purs` (config in `.tidyrc.json`), and LuaFormatter for the `*.lua` FFI +(config in `.lua-format`). LuaFormatter is used over StyLua because it keeps the +parentheses pslua's foreign-file parser requires. The Lua line budget is 130 +columns, matching the `luacheck --max-line-length` above. The check is +content-based (`nix fmt && git diff --exit-code`) rather than `treefmt --ci`, +since the in-place formatters bump mtime even when content is unchanged, which +trips treefmt's `--fail-on-change`. CI and the pre-commit hook use it. ## Lua 5.1 target diff --git a/bench/Data/Array.purs b/bench/Data/Array.purs index dc94c7d8..5080f257 100644 --- a/bench/Data/Array.purs +++ b/bench/Data/Array.purs @@ -17,9 +17,10 @@ benchArray = do where benchMapMaybe = do - let shortNats = Array.range 0 100 - longNats = Array.range 0 10000 - onlyEven x = if x `mod` 2 == 0 then Just x else Nothing + let + shortNats = Array.range 0 100 + longNats = Array.range 0 10000 + onlyEven x = if x `mod` 2 == 0 then Just x else Nothing log $ "mapMaybe (" <> show (Array.length shortNats) <> ")" benchWith 1000 \_ -> Array.mapMaybe onlyEven shortNats diff --git a/flake.lock b/flake.lock index 6b6c4177..c47b792e 100644 --- a/flake.lock +++ b/flake.lock @@ -740,7 +740,8 @@ "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", "pslua": "pslua", - "purescript-overlay": "purescript-overlay" + "purescript-overlay": "purescript-overlay", + "treefmt-nix": "treefmt-nix" } }, "stackage": { @@ -803,6 +804,26 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780220602, + "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 51988659..4d86c4b0 100644 --- a/flake.nix +++ b/flake.nix @@ -9,16 +9,33 @@ inputs.nixpkgs.follows = "nixpkgs"; }; pslua.url = "github:purescript-lua/purescript-lua"; + treefmt-nix = { + url = "github:numtide/treefmt-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = { self, nixpkgs, flake-utils, purescript-overlay, pslua }: - flake-utils.lib.eachDefaultSystem (system: + outputs = + { + self, + nixpkgs, + flake-utils, + purescript-overlay, + pslua, + treefmt-nix, + }: + flake-utils.lib.eachDefaultSystem ( + system: let pkgs = import nixpkgs { inherit system; overlays = [ purescript-overlay.overlays.default ]; }; - in { + treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix; + in + { + formatter = treefmtEval.config.build.wrapper; + checks.formatting = treefmtEval.config.build.check self; devShell = pkgs.mkShell { buildInputs = with pkgs; [ dhall @@ -31,8 +48,26 @@ spago-bin.spago-0_21_0 treefmt ]; + # Install a content-based pre-commit hook. It compares the working + # tree diff before and after `nix fmt`, so it only objects to changes + # the formatter itself introduces (not the developer's existing + # unstaged work) and is not fooled by formatters that only bump mtime. + # Rewritten each shell entry to stay in sync with this flake. + shellHook = '' + hook=.git/hooks/pre-commit + if [ -d .git ]; then + printf '%s\n' \ + '#!/usr/bin/env bash' \ + 'before=$(git diff)' \ + 'nix fmt >/dev/null 2>&1 || exit 0' \ + '[ "$before" = "$(git diff)" ] || { echo "nix fmt changed files; re-stage them, then commit." >&2; exit 1; }' \ + > "$hook" + chmod +x "$hook" + fi + ''; }; - }); + } + ); # --- Flake Local Nix Configuration ---------------------------- nixConfig = { diff --git a/src/Data/Array.lua b/src/Data/Array.lua index 733d37d9..dfd1a0f1 100644 --- a/src/Data/Array.lua +++ b/src/Data/Array.lua @@ -41,7 +41,7 @@ return { length = (function(xs) return #xs end), unconsImpl = (function(empty, next, xs) if #xs == 0 then return empty({}) end - return next(xs[1])({ unpack(xs, 2) }) + return next(xs[1])({unpack(xs, 2)}) end), indexImpl = (function(just, nothing, xs, i) if i < 0 or i >= #xs then @@ -67,19 +67,19 @@ return { end), _insertAt = (function(just, nothing, i, a, l) if i < 0 or i > #l then return nothing end - local l1 = { unpack(l) } + local l1 = {unpack(l)} table.insert(l1, i + 1, a) return just(l1) end), _deleteAt = (function(just, nothing, i, l) if i < 0 or i >= #l then return nothing end - local l1 = { unpack(l) } + local l1 = {unpack(l)} table.remove(l1, i + 1) return just(l1) end), _updateAt = (function(just, nothing, i, f, l) if i < 0 or i >= #l then return nothing end - local l1 = { unpack(l) } + local l1 = {unpack(l)} l1[i + 1] = f(l1[i + 1]) return just(l1) end), @@ -185,8 +185,8 @@ return { return function(compare, fromOrdering, xs) if #xs < 2 then return xs end - local out = { unpack(xs) } - local slice = { unpack(xs) } + local out = {unpack(xs)} + local slice = {unpack(xs)} mergeFromTo(compare, fromOrdering, out, slice, 0, #xs) return out end diff --git a/src/Data/Array.purs b/src/Data/Array.purs index 431f942a..a4d43f4d 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -720,7 +720,8 @@ splitAt i xs = { before: slice 0 i xs, after: slice i (length xs) xs } -- | powerSet :: forall a. Array a -> Array (Array a) -- | powerSet = filterA (const [true, false]) -- | ``` -filterA :: forall a f. Applicative f => (a -> f Boolean) -> Array a -> f (Array a) +filterA + :: forall a f. Applicative f => (a -> f Boolean) -> Array a -> f (Array a) filterA p = traverse (\x -> Tuple x <$> p x) >>> map (mapMaybe (\(Tuple x b) -> if b then Just x else Nothing)) @@ -771,9 +772,11 @@ mapWithIndex = FWI.mapWithIndex -- | updateAtIndices updates ["Hello", "World", "!"] = ["Hi", "World", "."] -- | ``` -- | -updateAtIndices :: forall t a. Foldable t => t (Tuple Int a) -> Array a -> Array a +updateAtIndices + :: forall t a. Foldable t => t (Tuple Int a) -> Array a -> Array a updateAtIndices us xs = - ST.run (STA.withArray (\res -> traverse_ (\(Tuple i a) -> STA.poke i a res) us) xs) + ST.run + (STA.withArray (\res -> traverse_ (\(Tuple i a) -> STA.poke i a res) us) xs) -- | Apply a function to the element at the specified indices, -- | creating a new array. Out-of-bounds indices will have no effect. @@ -784,7 +787,8 @@ updateAtIndices us xs = -- | = ["Hello", "WORLD", "and", "OTHERS"] -- | ``` -- | -modifyAtIndices :: forall t a. Foldable t => t Int -> (a -> a) -> Array a -> Array a +modifyAtIndices + :: forall t a. Foldable t => t Int -> (a -> a) -> Array a -> Array a modifyAtIndices is f xs = ST.run (STA.withArray (\res -> traverse_ (\i -> STA.modify i f res) is) xs) @@ -841,7 +845,8 @@ transpose xs = go 0 [] buildNext :: Int -> Maybe (Array a) buildNext idx = do xs # flip foldl Nothing \acc nextArr -> do - maybe acc (\el -> Just $ maybe [ el ] (flip snoc el) acc) $ index nextArr idx + maybe acc (\el -> Just $ maybe [ el ] (flip snoc el) acc) $ index nextArr + idx -- | Fold a data structure from the left, keeping all intermediate results -- | instead of only the final result. Note that the initial value does not @@ -911,7 +916,8 @@ sortBy comp = runFn3 sortByImpl comp case _ of sortWith :: forall a b. Ord b => (a -> b) -> Array a -> Array a sortWith f = sortBy (comparing f) -foreign import sortByImpl :: forall a. Fn3 (a -> a -> Ordering) (Ordering -> Int) (Array a) (Array a) +foreign import sortByImpl + :: forall a. Fn3 (a -> a -> Ordering) (Ordering -> Int) (Array a) (Array a) -------------------------------------------------------------------------------- -- Subarrays ------------------------------------------------------------------- @@ -1081,7 +1087,8 @@ groupBy op xs = -- | = [NonEmptyArray [4], NonEmptyArray [3, 3, 3], NonEmptyArray [2], NonEmptyArray [1]] -- | ``` -- | -groupAllBy :: forall a. (a -> a -> Ordering) -> Array a -> Array (NonEmptyArray a) +groupAllBy + :: forall a. (a -> a -> Ordering) -> Array a -> Array (NonEmptyArray a) groupAllBy cmp = groupBy (\x y -> cmp x y == EQ) <<< sortBy cmp -- | Remove the duplicates from an array, creating a new array. @@ -1118,7 +1125,8 @@ nubBy comp xs = case head indexedAndSorted of -- TODO: use NonEmptyArrays here to avoid partial functions result <- STA.unsafeThaw $ singleton x ST.foreach indexedAndSorted \pair@(Tuple _ x') -> do - lst <- snd <<< unsafePartial (fromJust <<< last) <$> STA.unsafeFreeze result + lst <- snd <<< unsafePartial (fromJust <<< last) <$> STA.unsafeFreeze + result when (comp lst x' /= EQ) $ void $ STA.push pair result STA.unsafeFreeze result where @@ -1192,7 +1200,8 @@ delete = deleteBy eq -- | deleteBy :: forall a. (a -> a -> Boolean) -> a -> Array a -> Array a deleteBy _ _ [] = [] -deleteBy eq x ys = maybe ys (\i -> unsafePartial $ fromJust (deleteAt i ys)) (findIndex (eq x) ys) +deleteBy eq x ys = maybe ys (\i -> unsafePartial $ fromJust (deleteAt i ys)) + (findIndex (eq x) ys) -- | Delete the first occurrence of each element in the second array from the -- | first array, creating a new array. @@ -1341,7 +1350,8 @@ foreign import allImpl :: forall a. Fn2 (a -> Boolean) (Array a) Boolean -- | foldM (\x y -> Just (x + y)) 0 [1, 4] = Just 5 -- | ``` foldM :: forall m a b. Monad m => (b -> a -> m b) -> b -> Array a -> m b -foldM f b = runFn3 unconsImpl (\_ -> pure b) (\a as -> f b a >>= \b' -> foldM f b' as) +foldM f b = runFn3 unconsImpl (\_ -> pure b) + (\a as -> f b a >>= \b' -> foldM f b' as) foldRecM :: forall m a b. MonadRec m => (b -> a -> m b) -> b -> Array a -> m b foldRecM f b array = tailRecM2 go b 0 diff --git a/src/Data/Array/NonEmpty.purs b/src/Data/Array/NonEmpty.purs index e69a7bf1..29fbfab3 100644 --- a/src/Data/Array/NonEmpty.purs +++ b/src/Data/Array/NonEmpty.purs @@ -10,13 +10,15 @@ module Data.Array.NonEmpty , toUnfoldable , toUnfoldable1 , singleton - , (..), range + , (..) + , range , replicate , some , length - , (:), cons + , (:) + , cons , cons' , snoc , snoc' @@ -32,7 +34,8 @@ module Data.Array.NonEmpty , uncons , unsnoc - , (!!), index + , (!!) + , index , elem , notElem , elemIndex @@ -97,7 +100,8 @@ module Data.Array.NonEmpty , delete , deleteBy - , (\\), difference + , (\\) + , difference , difference' , intersect , intersect' @@ -143,7 +147,8 @@ import Unsafe.Coerce (unsafeCoerce) -- -- Note that this is unsafe: if the transform returns an empty array, this can -- explode at runtime. -unsafeAdapt :: forall a b. (Array a -> Array b) -> NonEmptyArray a -> NonEmptyArray b +unsafeAdapt + :: forall a b. (Array a -> Array b) -> NonEmptyArray a -> NonEmptyArray b unsafeAdapt f = unsafeFromArray <<< adaptAny f -- | Internal - adapt an Array transform to NonEmptyArray, @@ -177,7 +182,7 @@ toArray :: forall a. NonEmptyArray a -> Array a toArray (NonEmptyArray xs) = xs toNonEmpty :: forall a. NonEmptyArray a -> NonEmpty Array a -toNonEmpty = uncons >>> \{head: x, tail: xs} -> x :| xs +toNonEmpty = uncons >>> \{ head: x, tail: xs } -> x :| xs fromFoldable :: forall f a. Foldable f => f a -> Maybe (NonEmptyArray a) fromFoldable = fromArray <<< A.fromFoldable @@ -193,7 +198,7 @@ toUnfoldable1 xs = unfoldr1 f 0 where len = length xs f i = Tuple (unsafePartial unsafeIndex xs i) $ - if i < (len - 1) then Just (i + 1) else Nothing + if i < (len - 1) then Just (i + 1) else Nothing singleton :: forall a. a -> NonEmptyArray a singleton = unsafeFromArray <<< A.singleton @@ -211,7 +216,8 @@ some :: forall f a . Alternative f => Lazy (f (Array a)) - => f a -> f (NonEmptyArray a) + => f a + -> f (NonEmptyArray a) some = unsafeFromArrayF <<< A.some length :: forall a. NonEmptyArray a -> Int @@ -240,7 +246,8 @@ prependArray xs ys = unsafeFromArray $ xs <> toArray ys insert :: forall a. Ord a => a -> NonEmptyArray a -> NonEmptyArray a insert x = unsafeAdapt $ A.insert x -insertBy :: forall a. (a -> a -> Ordering) -> a -> NonEmptyArray a -> NonEmptyArray a +insertBy + :: forall a. (a -> a -> Ordering) -> a -> NonEmptyArray a -> NonEmptyArray a insertBy f x = unsafeAdapt $ A.insertBy f x head :: forall a. NonEmptyArray a -> a @@ -299,13 +306,25 @@ deleteAt i = adaptAny $ A.deleteAt i updateAt :: forall a. Int -> a -> NonEmptyArray a -> Maybe (NonEmptyArray a) updateAt i x = unsafeFromArrayF <<< A.updateAt i x <<< toArray -updateAtIndices :: forall t a. Foldable t => t (Tuple Int a) -> NonEmptyArray a -> NonEmptyArray a +updateAtIndices + :: forall t a + . Foldable t + => t (Tuple Int a) + -> NonEmptyArray a + -> NonEmptyArray a updateAtIndices pairs = unsafeAdapt $ A.updateAtIndices pairs -modifyAt :: forall a. Int -> (a -> a) -> NonEmptyArray a -> Maybe (NonEmptyArray a) +modifyAt + :: forall a. Int -> (a -> a) -> NonEmptyArray a -> Maybe (NonEmptyArray a) modifyAt i f = unsafeFromArrayF <<< A.modifyAt i f <<< toArray -modifyAtIndices :: forall t a. Foldable t => t Int -> (a -> a) -> NonEmptyArray a -> NonEmptyArray a +modifyAtIndices + :: forall t a + . Foldable t + => t Int + -> (a -> a) + -> NonEmptyArray a + -> NonEmptyArray a modifyAtIndices is f = unsafeAdapt $ A.modifyAtIndices is f alterAt :: forall a. Int -> (a -> Maybe a) -> NonEmptyArray a -> Maybe (Array a) @@ -320,7 +339,8 @@ reverse = unsafeAdapt A.reverse concat :: forall a. NonEmptyArray (NonEmptyArray a) -> NonEmptyArray a concat = unsafeFromArray <<< A.concat <<< toArray <<< map toArray -concatMap :: forall a b. (a -> NonEmptyArray b) -> NonEmptyArray a -> NonEmptyArray b +concatMap + :: forall a b. (a -> NonEmptyArray b) -> NonEmptyArray a -> NonEmptyArray b concatMap = flip bind filter :: forall a. (a -> Boolean) -> NonEmptyArray a -> Array a @@ -330,7 +350,7 @@ partition :: forall a . (a -> Boolean) -> NonEmptyArray a - -> { yes :: Array a, no :: Array a} + -> { yes :: Array a, no :: Array a } partition f = adaptAny $ A.partition f filterA @@ -341,7 +361,8 @@ filterA -> f (Array a) filterA f = adaptAny $ A.filterA f -splitAt :: forall a. Int -> NonEmptyArray a -> { before :: Array a, after :: Array a } +splitAt + :: forall a. Int -> NonEmptyArray a -> { before :: Array a, after :: Array a } splitAt i xs = A.splitAt i $ toArray xs mapMaybe :: forall a b. (a -> Maybe b) -> NonEmptyArray a -> Array b @@ -350,7 +371,8 @@ mapMaybe f = adaptAny $ A.mapMaybe f catMaybes :: forall a. NonEmptyArray (Maybe a) -> Array a catMaybes = adaptAny A.catMaybes -mapWithIndex :: forall a b. (Int -> a -> b) -> NonEmptyArray a -> NonEmptyArray b +mapWithIndex + :: forall a b. (Int -> a -> b) -> NonEmptyArray a -> NonEmptyArray b mapWithIndex f = unsafeAdapt $ A.mapWithIndex f foldl1 :: forall a. (a -> a -> a) -> NonEmptyArray a -> a @@ -395,15 +417,20 @@ intercalate = F.intercalate -- | , NonEmptyArray [32] -- | ]) -- | ``` -transpose :: forall a. NonEmptyArray (NonEmptyArray a) -> NonEmptyArray (NonEmptyArray a) -transpose = - (coerce :: (Array (Array a)) -> (NonEmptyArray (NonEmptyArray a))) - <<< A.transpose <<< coerce +transpose + :: forall a + . NonEmptyArray (NonEmptyArray a) + -> NonEmptyArray (NonEmptyArray a) +transpose = + (coerce :: (Array (Array a)) -> (NonEmptyArray (NonEmptyArray a))) + <<< A.transpose + <<< coerce -- | `transpose`' is identical to `transpose` other than that the inner arrays are each -- | a standard `Array` and not a `NonEmptyArray`. However, the result is wrapped in a -- | `Maybe` to cater for the case where the inner `Array` is empty and must return `Nothing`. -transpose' :: forall a. NonEmptyArray (Array a) -> Maybe (NonEmptyArray (Array a)) +transpose' + :: forall a. NonEmptyArray (Array a) -> Maybe (NonEmptyArray (Array a)) transpose' = fromArray <<< A.transpose <<< coerce scanl :: forall a b. (b -> a -> b) -> b -> NonEmptyArray a -> NonEmptyArray b @@ -464,7 +491,8 @@ group = unsafeAdapt $ A.group -- | groupAll (NonEmptyArray [1, 1, 2, 2, 1]) == -- | NonEmptyArray [NonEmptyArray [1, 1, 1], NonEmptyArray [2, 2]] -- | ` -groupAll :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +groupAll + :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) groupAll = groupAllBy compare -- | Group equal, consecutive elements of an array into arrays, using the @@ -475,7 +503,11 @@ groupAll = groupAllBy compare -- | = NonEmptyArray [NonEmptyArray [1, 3], NonEmptyArray [2], NonEmptyArray [4], NonEmptyArray [3, 3]] -- | ``` -- | -groupBy :: forall a. (a -> a -> Boolean) -> NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +groupBy + :: forall a + . (a -> a -> Boolean) + -> NonEmptyArray a + -> NonEmptyArray (NonEmptyArray a) groupBy op = unsafeAdapt $ A.groupBy op -- | Group equal elements of an array into arrays, using the specified @@ -485,7 +517,11 @@ groupBy op = unsafeAdapt $ A.groupBy op -- | groupAllBy (comparing Down) (NonEmptyArray [1, 3, 2, 4, 3, 3]) -- | = NonEmptyArray [NonEmptyArray [4], NonEmptyArray [3, 3, 3], NonEmptyArray [2], NonEmptyArray [1]] -- | ``` -groupAllBy :: forall a. (a -> a -> Ordering) -> NonEmptyArray a -> NonEmptyArray (NonEmptyArray a) +groupAllBy + :: forall a + . (a -> a -> Ordering) + -> NonEmptyArray a + -> NonEmptyArray (NonEmptyArray a) groupAllBy op = unsafeAdapt $ A.groupAllBy op nub :: forall a. Ord a => NonEmptyArray a -> NonEmptyArray a @@ -534,10 +570,10 @@ difference xs = adaptAny $ difference' xs difference' :: forall a. Eq a => NonEmptyArray a -> Array a -> Array a difference' xs = A.difference $ toArray xs -intersect :: forall a . Eq a => NonEmptyArray a -> NonEmptyArray a -> Array a +intersect :: forall a. Eq a => NonEmptyArray a -> NonEmptyArray a -> Array a intersect = intersectBy eq -intersect' :: forall a . Eq a => NonEmptyArray a -> Array a -> Array a +intersect' :: forall a. Eq a => NonEmptyArray a -> Array a -> Array a intersect' = intersectBy' eq intersectBy @@ -566,7 +602,6 @@ zipWith -> NonEmptyArray c zipWith f xs ys = unsafeFromArray $ A.zipWith f (toArray xs) (toArray ys) - zipWithA :: forall m a b c . Applicative m @@ -576,10 +611,14 @@ zipWithA -> m (NonEmptyArray c) zipWithA f xs ys = unsafeFromArrayF $ A.zipWithA f (toArray xs) (toArray ys) -zip :: forall a b. NonEmptyArray a -> NonEmptyArray b -> NonEmptyArray (Tuple a b) +zip + :: forall a b. NonEmptyArray a -> NonEmptyArray b -> NonEmptyArray (Tuple a b) zip xs ys = unsafeFromArray $ toArray xs `A.zip` toArray ys -unzip :: forall a b. NonEmptyArray (Tuple a b) -> Tuple (NonEmptyArray a) (NonEmptyArray b) +unzip + :: forall a b + . NonEmptyArray (Tuple a b) + -> Tuple (NonEmptyArray a) (NonEmptyArray b) unzip = bimap unsafeFromArray unsafeFromArray <<< A.unzip <<< toArray any :: forall a. (a -> Boolean) -> NonEmptyArray a -> Boolean @@ -591,7 +630,8 @@ all p = adaptAny $ A.all p foldM :: forall m a b. Monad m => (b -> a -> m b) -> b -> NonEmptyArray a -> m b foldM f acc = adaptAny $ A.foldM f acc -foldRecM :: forall m a b. MonadRec m => (b -> a -> m b) -> b -> NonEmptyArray a -> m b +foldRecM + :: forall m a b. MonadRec m => (b -> a -> m b) -> b -> NonEmptyArray a -> m b foldRecM f acc = adaptAny $ A.foldRecM f acc unsafeIndex :: forall a. Partial => NonEmptyArray a -> Int -> a diff --git a/src/Data/Array/NonEmpty/Internal.purs b/src/Data/Array/NonEmpty/Internal.purs index 752ada6e..e17adb40 100644 --- a/src/Data/Array/NonEmpty/Internal.purs +++ b/src/Data/Array/NonEmpty/Internal.purs @@ -43,10 +43,12 @@ derive newtype instance ord1NonEmptyArray :: Ord1 NonEmptyArray derive newtype instance semigroupNonEmptyArray :: Semigroup (NonEmptyArray a) derive newtype instance functorNonEmptyArray :: Functor NonEmptyArray -derive newtype instance functorWithIndexNonEmptyArray :: FunctorWithIndex Int NonEmptyArray +derive newtype instance functorWithIndexNonEmptyArray :: + FunctorWithIndex Int NonEmptyArray derive newtype instance foldableNonEmptyArray :: Foldable NonEmptyArray -derive newtype instance foldableWithIndexNonEmptyArray :: FoldableWithIndex Int NonEmptyArray +derive newtype instance foldableWithIndexNonEmptyArray :: + FoldableWithIndex Int NonEmptyArray instance foldable1NonEmptyArray :: Foldable1 NonEmptyArray where foldMap1 = foldMap1DefaultL @@ -55,7 +57,8 @@ instance foldable1NonEmptyArray :: Foldable1 NonEmptyArray where derive newtype instance unfoldable1NonEmptyArray :: Unfoldable1 NonEmptyArray derive newtype instance traversableNonEmptyArray :: Traversable NonEmptyArray -derive newtype instance traversableWithIndexNonEmptyArray :: TraversableWithIndex Int NonEmptyArray +derive newtype instance traversableWithIndexNonEmptyArray :: + TraversableWithIndex Int NonEmptyArray instance traversable1NonEmptyArray :: Traversable1 NonEmptyArray where traverse1 f = runFn3 traverse1Impl apply map f diff --git a/src/Data/Array/ST.purs b/src/Data/Array/ST.purs index 5ff3c1a7..0e9370fe 100644 --- a/src/Data/Array/ST.purs +++ b/src/Data/Array/ST.purs @@ -106,7 +106,8 @@ shift = runSTFn3 shiftImpl Just Nothing foreign import shiftImpl :: forall h a - . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h (Maybe a) + . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h + (Maybe a) -- | Sort a mutable array in place using a comparison function. Sorting is -- | stable: the order of elements is preserved if they are equal according to @@ -177,7 +178,8 @@ pop = runSTFn3 popImpl Just Nothing foreign import popImpl :: forall h a - . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h (Maybe a) + . STFn3 (forall b. b -> Maybe b) (forall b. Maybe b) (STArray h a) h + (Maybe a) -- | Append an element to the end of a mutable array. Returns the new length of -- | the array. diff --git a/src/Data/Array/ST/Iterator.purs b/src/Data/Array/ST/Iterator.purs index 09daf0ed..d46b22a9 100644 --- a/src/Data/Array/ST/Iterator.purs +++ b/src/Data/Array/ST/Iterator.purs @@ -63,7 +63,8 @@ exhausted = map isNothing <<< peek -- | Extract elements from an iterator and push them on to an STArray for as -- | long as those elements satisfy a given predicate. -pushWhile :: forall r a. (a -> Boolean) -> Iterator r a -> STArray r a -> ST r Unit +pushWhile + :: forall r a. (a -> Boolean) -> Iterator r a -> STArray r a -> ST r Unit pushWhile p iter array = do break <- STRef.new false ST.while (not <$> STRef.read break) do diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index e2d7b0fe..8939a5f1 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -22,83 +22,89 @@ testArray :: Effect Unit testArray = do log "singleton should construct an array with a single value" - assert $ A.singleton 1 == [1] - assert $ A.singleton "foo" == ["foo"] - assert $ A.singleton nil == [[]] - - log "range should create an inclusive array of integers for the specified start and end" - assert $ (A.range 0 5) == [0, 1, 2, 3, 4, 5] - assert $ (A.range 2 (-3)) == [2, 1, 0, -1, -2, -3] - - log "replicate should produce an array containg an item a specified number of times" - assert $ A.replicate 3 true == [true, true, true] - assert $ A.replicate 1 "foo" == ["foo"] + assert $ A.singleton 1 == [ 1 ] + assert $ A.singleton "foo" == [ "foo" ] + assert $ A.singleton nil == [ [] ] + + log + "range should create an inclusive array of integers for the specified start and end" + assert $ (A.range 0 5) == [ 0, 1, 2, 3, 4, 5 ] + assert $ (A.range 2 (-3)) == [ 2, 1, 0, -1, -2, -3 ] + + log + "replicate should produce an array containg an item a specified number of times" + assert $ A.replicate 3 true == [ true, true, true ] + assert $ A.replicate 1 "foo" == [ "foo" ] assert $ A.replicate 0 "foo" == [] assert $ A.replicate (-1) "foo" == [] log "replicateA should perform the monadic action the correct number of times" - assert $ replicateA 3 (Just 1) == Just [1, 1, 1] - assert $ replicateA 1 (Just 1) == Just [1] + assert $ replicateA 3 (Just 1) == Just [ 1, 1, 1 ] + assert $ replicateA 1 (Just 1) == Just [ 1 ] assert $ replicateA 0 (Just 1) == Just [] assert $ replicateA (-1) (Just 1) == Just [] log "replicateA should be stack safe" - for_ [1, 1000, 2000, 20000, 50000] \n -> do + for_ [ 1, 1000, 2000, 20000, 50000 ] \n -> do assert $ replicateA n (Just unit) == Just (A.replicate n unit :: Array Unit) -- some -- many log "null should return false for non-empty arrays" - assert $ A.null [1] == false - assert $ A.null [1, 2, 3] == false + assert $ A.null [ 1 ] == false + assert $ A.null [ 1, 2, 3 ] == false log "null should return true for an empty array" assert $ A.null nil == true log "length should return the number of items in an array" assert $ A.length nil == 0 - assert $ A.length [1] == 1 - assert $ A.length [1, 2, 3, 4, 5] == 5 + assert $ A.length [ 1 ] == 1 + assert $ A.length [ 1, 2, 3, 4, 5 ] == 5 log "cons should add an item to the start of an array" - assert $ 4 : [1, 2, 3] == [4, 1, 2, 3] - assert $ 1 : nil == [1] + assert $ 4 : [ 1, 2, 3 ] == [ 4, 1, 2, 3 ] + assert $ 1 : nil == [ 1 ] log "snoc should add an item to the end of an array" - assert $ [1, 2, 3] `A.snoc` 4 == [1, 2, 3, 4] - assert $ nil `A.snoc` 1 == [1] + assert $ [ 1, 2, 3 ] `A.snoc` 4 == [ 1, 2, 3, 4 ] + assert $ nil `A.snoc` 1 == [ 1 ] log "insert should add an item at the appropriate place in a sorted array" - assert $ A.insert 1.5 [1.0, 2.0, 3.0] == [1.0, 1.5, 2.0, 3.0] - assert $ A.insert 4 [1, 2, 3] == [1, 2, 3, 4] - assert $ A.insert 0 [1, 2, 3] == [0, 1, 2, 3] + assert $ A.insert 1.5 [ 1.0, 2.0, 3.0 ] == [ 1.0, 1.5, 2.0, 3.0 ] + assert $ A.insert 4 [ 1, 2, 3 ] == [ 1, 2, 3, 4 ] + assert $ A.insert 0 [ 1, 2, 3 ] == [ 0, 1, 2, 3 ] - log "insertBy should add an item at the appropriate place in a sorted array using the specified comparison" - assert $ A.insertBy (flip compare) 1.5 [1.0, 2.0, 3.0] == [1.0, 2.0, 3.0, 1.5] - assert $ A.insertBy (flip compare) 4 [1, 2, 3] == [4, 1, 2, 3] - assert $ A.insertBy (flip compare) 0 [1, 2, 3] == [1, 2, 3, 0] + log + "insertBy should add an item at the appropriate place in a sorted array using the specified comparison" + assert $ A.insertBy (flip compare) 1.5 [ 1.0, 2.0, 3.0 ] == + [ 1.0, 2.0, 3.0, 1.5 ] + assert $ A.insertBy (flip compare) 4 [ 1, 2, 3 ] == [ 4, 1, 2, 3 ] + assert $ A.insertBy (flip compare) 0 [ 1, 2, 3 ] == [ 1, 2, 3, 0 ] log "head should return a Just-wrapped first value of a non-empty array" - assert $ A.head ["foo", "bar"] == Just "foo" + assert $ A.head [ "foo", "bar" ] == Just "foo" log "head should return Nothing for an empty array" assert $ A.head nil == Nothing log "last should return a Just-wrapped last value of a non-empty array" - assert $ A.last ["foo", "bar"] == Just "bar" + assert $ A.last [ "foo", "bar" ] == Just "bar" log "last should return Nothing for an empty array" assert $ A.last nil == Nothing - log "tail should return a Just-wrapped array containing all the items in an array apart from the first for a non-empty array" - assert $ A.tail ["foo", "bar", "baz"] == Just ["bar", "baz"] + log + "tail should return a Just-wrapped array containing all the items in an array apart from the first for a non-empty array" + assert $ A.tail [ "foo", "bar", "baz" ] == Just [ "bar", "baz" ] log "tail should return Nothing for an empty array" assert $ A.tail nil == Nothing - log "init should return a Just-wrapped array containing all the items in an array apart from the first for a non-empty array" - assert $ A.init ["foo", "bar", "baz"] == Just ["foo", "bar"] + log + "init should return a Just-wrapped array containing all the items in an array apart from the first for a non-empty array" + assert $ A.init [ "foo", "bar", "baz" ] == Just [ "foo", "bar" ] log "init should return Nothing for an empty array" assert $ A.init nil == Nothing @@ -106,255 +112,295 @@ testArray = do log "uncons should return nothing when used on an empty array" assert $ isNothing (A.uncons nil) - log "uncons should split an array into a head and tail record when there is at least one item" - let u1 = unsafePartial $ fromJust $ A.uncons [1] + log + "uncons should split an array into a head and tail record when there is at least one item" + let u1 = unsafePartial $ fromJust $ A.uncons [ 1 ] assert $ u1.head == 1 assert $ u1.tail == [] - let u2 = unsafePartial $ fromJust $ A.uncons [1, 2, 3] + let u2 = unsafePartial $ fromJust $ A.uncons [ 1, 2, 3 ] assert $ u2.head == 1 - assert $ u2.tail == [2, 3] + assert $ u2.tail == [ 2, 3 ] log "unsnoc should return nothing when used on an empty array" assert $ isNothing (A.unsnoc nil) - log "unsnoc should split an array into an init and last record when there is at least one item" - let u3 = unsafePartial $ fromJust $ A.unsnoc [1] + log + "unsnoc should split an array into an init and last record when there is at least one item" + let u3 = unsafePartial $ fromJust $ A.unsnoc [ 1 ] assert $ u3.init == [] assert $ u3.last == 1 - let u4 = unsafePartial $ fromJust $ A.unsnoc [1, 2, 3] - assert $ u4.init == [1, 2] + let u4 = unsafePartial $ fromJust $ A.unsnoc [ 1, 2, 3 ] + assert $ u4.init == [ 1, 2 ] assert $ u4.last == 3 - log "(!!) should return Just x when the index is within the bounds of the array" - assert $ [1, 2, 3] !! 0 == (Just 1) - assert $ [1, 2, 3] !! 1 == (Just 2) - assert $ [1, 2, 3] !! 2 == (Just 3) + log + "(!!) should return Just x when the index is within the bounds of the array" + assert $ [ 1, 2, 3 ] !! 0 == (Just 1) + assert $ [ 1, 2, 3 ] !! 1 == (Just 2) + assert $ [ 1, 2, 3 ] !! 2 == (Just 3) - log "(!!) should return Nothing when the index is outside of the bounds of the array" - assert $ [1, 2, 3] !! 6 == Nothing - assert $ [1, 2, 3] !! (-1) == Nothing + log + "(!!) should return Nothing when the index is outside of the bounds of the array" + assert $ [ 1, 2, 3 ] !! 6 == Nothing + assert $ [ 1, 2, 3 ] !! (-1) == Nothing - log "elem should return true if the array contains the given element at least once" - assert $ (A.elem 1 [1, 2, 1]) == true - assert $ (A.elem 4 [1, 2, 1]) == false + log + "elem should return true if the array contains the given element at least once" + assert $ (A.elem 1 [ 1, 2, 1 ]) == true + assert $ (A.elem 4 [ 1, 2, 1 ]) == false - log "notElem should return true if the array does not contain the given element" - assert $ (A.notElem 1 [1, 2, 1]) == false - assert $ (A.notElem 4 [1, 2, 1]) == true + log + "notElem should return true if the array does not contain the given element" + assert $ (A.notElem 1 [ 1, 2, 1 ]) == false + assert $ (A.notElem 4 [ 1, 2, 1 ]) == true - log "elemIndex should return the index of an item that a predicate returns true for in an array" - assert $ (A.elemIndex 1 [1, 2, 1]) == Just 0 - assert $ (A.elemIndex 4 [1, 2, 1]) == Nothing + log + "elemIndex should return the index of an item that a predicate returns true for in an array" + assert $ (A.elemIndex 1 [ 1, 2, 1 ]) == Just 0 + assert $ (A.elemIndex 4 [ 1, 2, 1 ]) == Nothing log "elemLastIndex should return the last index of an item in an array" - assert $ (A.elemLastIndex 1 [1, 2, 1]) == Just 2 - assert $ (A.elemLastIndex 4 [1, 2, 1]) == Nothing - - log "find should return the first element for which a predicate returns true in an array" - assert $ (A.find (_ /= 1) [1, 2, 1]) == Just 2 - assert $ (A.find (_ == 3) [1, 2, 1]) == Nothing - - log "findMap should return the mapping of the first element that satisfies the given predicate" - assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [1, 2, 4]) == Just 4 - assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [1, 2, 1]) == Nothing - assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [4, 1, 5]) == Just 4 - - log "findIndex should return the index of an item that a predicate returns true for in an array" - assert $ (A.findIndex (_ /= 1) [1, 2, 1]) == Just 1 - assert $ (A.findIndex (_ == 3) [1, 2, 1]) == Nothing + assert $ (A.elemLastIndex 1 [ 1, 2, 1 ]) == Just 2 + assert $ (A.elemLastIndex 4 [ 1, 2, 1 ]) == Nothing + + log + "find should return the first element for which a predicate returns true in an array" + assert $ (A.find (_ /= 1) [ 1, 2, 1 ]) == Just 2 + assert $ (A.find (_ == 3) [ 1, 2, 1 ]) == Nothing + + log + "findMap should return the mapping of the first element that satisfies the given predicate" + assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [ 1, 2, 4 ]) == + Just 4 + assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [ 1, 2, 1 ]) == + Nothing + assert $ (A.findMap (\x -> if x > 3 then Just x else Nothing) [ 4, 1, 5 ]) == + Just 4 + + log + "findIndex should return the index of an item that a predicate returns true for in an array" + assert $ (A.findIndex (_ /= 1) [ 1, 2, 1 ]) == Just 1 + assert $ (A.findIndex (_ == 3) [ 1, 2, 1 ]) == Nothing log "findLastIndex should return the last index of an item in an array" - assert $ (A.findLastIndex (_ /= 1) [2, 1, 2]) == Just 2 - assert $ (A.findLastIndex (_ == 3) [2, 1, 2]) == Nothing + assert $ (A.findLastIndex (_ /= 1) [ 2, 1, 2 ]) == Just 2 + assert $ (A.findLastIndex (_ == 3) [ 2, 1, 2 ]) == Nothing log "insertAt should add an item at the specified index" - assert $ (A.insertAt 0 1 [2, 3]) == Just [1, 2, 3] - assert $ (A.insertAt 1 1 [2, 3]) == Just [2, 1, 3] - assert $ (A.insertAt 2 1 [2, 3]) == Just [2, 3, 1] + assert $ (A.insertAt 0 1 [ 2, 3 ]) == Just [ 1, 2, 3 ] + assert $ (A.insertAt 1 1 [ 2, 3 ]) == Just [ 2, 1, 3 ] + assert $ (A.insertAt 2 1 [ 2, 3 ]) == Just [ 2, 3, 1 ] log "insertAt should return Nothing if the index is out of A.range" assert $ (A.insertAt 2 1 nil) == Nothing log "deleteAt should remove an item at the specified index" - assert $ (A.deleteAt 0 [1, 2, 3]) == Just [2, 3] - assert $ (A.deleteAt 1 [1, 2, 3]) == Just [1, 3] + assert $ (A.deleteAt 0 [ 1, 2, 3 ]) == Just [ 2, 3 ] + assert $ (A.deleteAt 1 [ 1, 2, 3 ]) == Just [ 1, 3 ] log "deleteAt should return Nothing if the index is out of A.range" assert $ (A.deleteAt 1 nil) == Nothing log "updateAt should replace an item at the specified index" - assert $ (A.updateAt 0 9 [1, 2, 3]) == Just [9, 2, 3] - assert $ (A.updateAt 1 9 [1, 2, 3]) == Just [1, 9, 3] + assert $ (A.updateAt 0 9 [ 1, 2, 3 ]) == Just [ 9, 2, 3 ] + assert $ (A.updateAt 1 9 [ 1, 2, 3 ]) == Just [ 1, 9, 3 ] log "updateAt should return Nothing if the index is out of A.range" assert $ (A.updateAt 1 9 nil) == Nothing log "modifyAt should update an item at the specified index" - assert $ (A.modifyAt 0 (_ + 1) [1, 2, 3]) == Just [2, 2, 3] - assert $ (A.modifyAt 1 (_ + 1) [1, 2, 3]) == Just [1, 3, 3] + assert $ (A.modifyAt 0 (_ + 1) [ 1, 2, 3 ]) == Just [ 2, 2, 3 ] + assert $ (A.modifyAt 1 (_ + 1) [ 1, 2, 3 ]) == Just [ 1, 3, 3 ] log "modifyAt should return Nothing if the index is out of A.range" assert $ (A.modifyAt 1 (_ + 1) nil) == Nothing - log "alterAt should update an item at the specified index when the function returns Just" - assert $ (A.alterAt 0 (Just <<< (_ + 1)) [1, 2, 3]) == Just [2, 2, 3] - assert $ (A.alterAt 1 (Just <<< (_ + 1)) [1, 2, 3]) == Just [1, 3, 3] + log + "alterAt should update an item at the specified index when the function returns Just" + assert $ (A.alterAt 0 (Just <<< (_ + 1)) [ 1, 2, 3 ]) == Just [ 2, 2, 3 ] + assert $ (A.alterAt 1 (Just <<< (_ + 1)) [ 1, 2, 3 ]) == Just [ 1, 3, 3 ] - log "alterAt should drop an item at the specified index when the function returns Nothing" - assert $ (A.alterAt 0 (const Nothing) [1, 2, 3]) == Just [2, 3] - assert $ (A.alterAt 1 (const Nothing) [1, 2, 3]) == Just [1, 3] + log + "alterAt should drop an item at the specified index when the function returns Nothing" + assert $ (A.alterAt 0 (const Nothing) [ 1, 2, 3 ]) == Just [ 2, 3 ] + assert $ (A.alterAt 1 (const Nothing) [ 1, 2, 3 ]) == Just [ 1, 3 ] log "alterAt should return Nothing if the index is out of A.range" assert $ (A.alterAt 1 (Just <<< (_ + 1)) nil) == Nothing - log "intersperse should return the original array when given an array with zero or one elements" + log + "intersperse should return the original array when given an array with zero or one elements" assert $ (A.intersperse " " []) == [] - assert $ (A.intersperse " " ["a"]) == ["a"] + assert $ (A.intersperse " " [ "a" ]) == [ "a" ] - log "intersperse should insert the given element in-between each element in an array with two or more elements" - assert $ (A.intersperse " " ["a", "b"]) == ["a", " ", "b"] + log + "intersperse should insert the given element in-between each element in an array with two or more elements" + assert $ (A.intersperse " " [ "a", "b" ]) == [ "a", " ", "b" ] assert $ (A.intersperse 0 [ 1, 2, 3, 4, 5 ]) == [ 1, 0, 2, 0, 3, 0, 4, 0, 5 ] log "reverse should reverse the order of items in an array" - assert $ (A.reverse [1, 2, 3]) == [3, 2, 1] + assert $ (A.reverse [ 1, 2, 3 ]) == [ 3, 2, 1 ] assert $ (A.reverse nil) == nil log "concat should join an array of arrays" - assert $ (A.concat [[1, 2], [3, 4]]) == [1, 2, 3, 4] - assert $ (A.concat [[1], nil]) == [1] - assert $ (A.concat [nil, nil]) == nil + assert $ (A.concat [ [ 1, 2 ], [ 3, 4 ] ]) == [ 1, 2, 3, 4 ] + assert $ (A.concat [ [ 1 ], nil ]) == [ 1 ] + assert $ (A.concat [ nil, nil ]) == nil log "concatMap should be equivalent to (concat <<< map)" - assert $ A.concatMap doubleAndOrig [1, 2, 3] == A.concat (map doubleAndOrig [1, 2, 3]) + assert $ A.concatMap doubleAndOrig [ 1, 2, 3 ] == A.concat + (map doubleAndOrig [ 1, 2, 3 ]) log "filter should remove items that don't match a predicate" - assert $ A.filter odd (A.range 0 10) == [1, 3, 5, 7, 9] + assert $ A.filter odd (A.range 0 10) == [ 1, 3, 5, 7, 9 ] log "splitAt should split the array at the given number of elements" assert $ A.splitAt 2 ([] :: Array Int) == { before: [], after: [] } - assert $ A.splitAt 3 [1, 2, 3, 4, 5] == { before: [1, 2, 3], after: [4, 5] } - assert $ A.splitAt 1 [1, 2, 3] == { before: [1], after: [2, 3] } - assert $ A.splitAt 3 [1, 2, 3] == { before: [1, 2, 3], after: [] } - assert $ A.splitAt 4 [1, 2, 3] == { before: [1, 2, 3], after: [] } - assert $ A.splitAt 0 [1, 2, 3] == { before: [], after: [1, 2, 3] } - assert $ A.splitAt (-1) [1, 2, 3] == { before: [], after: [1, 2, 3] } - - log "filterA should remove items that don't match a predicate while using an applicative behaviour" - assert $ A.filterA (Just <<< odd) (A.range 0 10) == Just [1, 3, 5, 7, 9] + assert $ A.splitAt 3 [ 1, 2, 3, 4, 5 ] == + { before: [ 1, 2, 3 ], after: [ 4, 5 ] } + assert $ A.splitAt 1 [ 1, 2, 3 ] == { before: [ 1 ], after: [ 2, 3 ] } + assert $ A.splitAt 3 [ 1, 2, 3 ] == { before: [ 1, 2, 3 ], after: [] } + assert $ A.splitAt 4 [ 1, 2, 3 ] == { before: [ 1, 2, 3 ], after: [] } + assert $ A.splitAt 0 [ 1, 2, 3 ] == { before: [], after: [ 1, 2, 3 ] } + assert $ A.splitAt (-1) [ 1, 2, 3 ] == { before: [], after: [ 1, 2, 3 ] } + + log + "filterA should remove items that don't match a predicate while using an applicative behaviour" + assert $ A.filterA (Just <<< odd) (A.range 0 10) == Just [ 1, 3, 5, 7, 9 ] assert $ A.filterA (const Nothing) (A.range 0 10) == Nothing log "filterA should apply effects in the right order" assert $ A.filterA (Const <<< show) (A.range 1 5) == Const "12345" - log "mapMaybe should transform every item in an array, throwing out Nothing values" - assert $ A.mapMaybe (\x -> if x /= 0 then Just x else Nothing) [0, 1, 0, 0, 2, 3] == [1, 2, 3] + log + "mapMaybe should transform every item in an array, throwing out Nothing values" + assert $ + A.mapMaybe (\x -> if x /= 0 then Just x else Nothing) [ 0, 1, 0, 0, 2, 3 ] + == [ 1, 2, 3 ] log "catMaybe should take an array of Maybe values and throw out Nothings" - assert $ A.catMaybes [Nothing, Just 2, Nothing, Just 4] == [2, 4] + assert $ A.catMaybes [ Nothing, Just 2, Nothing, Just 4 ] == [ 2, 4 ] log "mapWithIndex applies a function with an index for every element" - assert $ A.mapWithIndex (\i x -> x - i) [9,8,7,6,5] == [9,7,5,3,1] + assert $ A.mapWithIndex (\i x -> x - i) [ 9, 8, 7, 6, 5 ] == [ 9, 7, 5, 3, 1 ] log "updateAtIndices changes the elements at specified indices" - assert $ A.updateAtIndices - [Tuple 0 false, Tuple 2 false, Tuple 8 false] - [true, true, true, true] == - [false, true, false, true] + assert $ + A.updateAtIndices + [ Tuple 0 false, Tuple 2 false, Tuple 8 false ] + [ true, true, true, true ] == + [ false, true, false, true ] log "modifyAtIndices modifies the elements at specified indices" - assert $ A.modifyAtIndices [0, 2, 8] not [true, true, true, true] == - [false, true, false, true] + assert $ A.modifyAtIndices [ 0, 2, 8 ] not [ true, true, true, true ] == + [ false, true, false, true ] log "transpose swaps rows and columns for a regular two-dimension array" - assert $ A.transpose [[1,2,3], [4,5,6], [7,8,9]] == - [[1,4,7], [2,5,8], [3,6,9]] - + assert $ A.transpose [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] == + [ [ 1, 4, 7 ], [ 2, 5, 8 ], [ 3, 6, 9 ] ] + log "transpose skips elements when rows don't match" - assert $ A.transpose [[10,11], [20], [30,31,32]] == - [[10,20,30], [11,31], [32]] + assert $ A.transpose [ [ 10, 11 ], [ 20 ], [ 30, 31, 32 ] ] == + [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ] log "transpose [] == []" assert $ A.transpose [] == ([] :: Array (Array Int)) log "transpose (singleton []) == []" - assert $ A.transpose (A.singleton []) == ([] :: Array (Array Int)) + assert $ A.transpose (A.singleton []) == ([] :: Array (Array Int)) - log "scanl should return an array that stores the accumulated value at each step" - assert $ A.scanl (+) 0 [1,2,3] == [1, 3, 6] - assert $ A.scanl (-) 10 [1,2,3] == [9, 7, 4] + log + "scanl should return an array that stores the accumulated value at each step" + assert $ A.scanl (+) 0 [ 1, 2, 3 ] == [ 1, 3, 6 ] + assert $ A.scanl (-) 10 [ 1, 2, 3 ] == [ 9, 7, 4 ] log "scanl should return the same results as its Foldable counterpart" - assert $ A.scanl (+) 0 [1,2,3] == scanl (+) 0 [1,2,3] - assert $ A.scanl (-) 10 [1,2,3] == scanl (-) 10 [1,2,3] + assert $ A.scanl (+) 0 [ 1, 2, 3 ] == scanl (+) 0 [ 1, 2, 3 ] + assert $ A.scanl (-) 10 [ 1, 2, 3 ] == scanl (-) 10 [ 1, 2, 3 ] - log "scanr should return an array that stores the accumulated value at each step" - assert $ A.scanr (+) 0 [1,2,3] == [6,5,3] - assert $ A.scanr (flip (-)) 10 [1,2,3] == [4,5,7] + log + "scanr should return an array that stores the accumulated value at each step" + assert $ A.scanr (+) 0 [ 1, 2, 3 ] == [ 6, 5, 3 ] + assert $ A.scanr (flip (-)) 10 [ 1, 2, 3 ] == [ 4, 5, 7 ] log "scanr should return the same results as its Foldable counterpart" - assert $ A.scanr (+) 0 [1,2,3] == scanr (+) 0 [1,2,3] - assert $ A.scanr (flip (-)) 10 [1,2,3] == scanr (flip (-)) 10 [1,2,3] + assert $ A.scanr (+) 0 [ 1, 2, 3 ] == scanr (+) 0 [ 1, 2, 3 ] + assert $ A.scanr (flip (-)) 10 [ 1, 2, 3 ] == scanr (flip (-)) 10 [ 1, 2, 3 ] - log "sort should reorder a list into ascending order based on the result of compare" - assert $ A.sort [1, 3, 2, 5, 6, 4] == [1, 2, 3, 4, 5, 6] - assert $ A.sort [defined 1, undefined, defined 2] == [undefined, defined 1, defined 2] + log + "sort should reorder a list into ascending order based on the result of compare" + assert $ A.sort [ 1, 3, 2, 5, 6, 4 ] == [ 1, 2, 3, 4, 5, 6 ] + assert $ A.sort [ defined 1, undefined, defined 2 ] == + [ undefined, defined 1, defined 2 ] - log "sortBy should reorder a list into ascending order based on the result of a comparison function" - assert $ A.sortBy (flip compare) [1, 3, 2, 5, 6, 4] == [6, 5, 4, 3, 2, 1] + log + "sortBy should reorder a list into ascending order based on the result of a comparison function" + assert $ A.sortBy (flip compare) [ 1, 3, 2, 5, 6, 4 ] == [ 6, 5, 4, 3, 2, 1 ] - log "sortBy should not reorder elements that are equal according to a comparison function" + log + "sortBy should not reorder elements that are equal according to a comparison function" let s1 = map (Tuple "a") (A.range 1 100) assert $ A.sortBy (comparing fst) s1 == s1 - log "sortWith should reorder a list into ascending order based on the result of compare over a projection" - assert $ A.sortWith identity [1, 3, 2, 5, 6, 4] == [1, 2, 3, 4, 5, 6] + log + "sortWith should reorder a list into ascending order based on the result of compare over a projection" + assert $ A.sortWith identity [ 1, 3, 2, 5, 6, 4 ] == [ 1, 2, 3, 4, 5, 6 ] - log "sortWith should not reorder elements that are equal according to a projection" + log + "sortWith should not reorder elements that are equal according to a projection" let s2 = map (Tuple "a") (A.range 1 100) assert $ A.sortWith fst s2 == s2 - log "take should keep the specified number of items from the front of an array, discarding the rest" - assert $ (A.take 1 [1, 2, 3]) == [1] - assert $ (A.take 2 [1, 2, 3]) == [1, 2] + log + "take should keep the specified number of items from the front of an array, discarding the rest" + assert $ (A.take 1 [ 1, 2, 3 ]) == [ 1 ] + assert $ (A.take 2 [ 1, 2, 3 ]) == [ 1, 2 ] assert $ (A.take 1 nil) == nil - log "takeWhile should keep all values that match a predicate from the front of an array" - assert $ (A.takeWhile (_ /= 2) [1, 2, 3]) == [1] - assert $ (A.takeWhile (_ /= 3) [1, 2, 3]) == [1, 2] + log + "takeWhile should keep all values that match a predicate from the front of an array" + assert $ (A.takeWhile (_ /= 2) [ 1, 2, 3 ]) == [ 1 ] + assert $ (A.takeWhile (_ /= 3) [ 1, 2, 3 ]) == [ 1, 2 ] assert $ (A.takeWhile (_ /= 1) nil) == nil - log "take should keep the specified number of items from the end of an array, discarding the rest" - assert $ (A.takeEnd 1 [1, 2, 3]) == [3] - assert $ (A.takeEnd 2 [1, 2, 3]) == [2, 3] + log + "take should keep the specified number of items from the end of an array, discarding the rest" + assert $ (A.takeEnd 1 [ 1, 2, 3 ]) == [ 3 ] + assert $ (A.takeEnd 2 [ 1, 2, 3 ]) == [ 2, 3 ] assert $ (A.takeEnd 1 nil) == nil - log "drop should remove the specified number of items from the front of an array" - assert $ (A.drop 1 [1, 2, 3]) == [2, 3] - assert $ (A.drop 2 [1, 2, 3]) == [3] + log + "drop should remove the specified number of items from the front of an array" + assert $ (A.drop 1 [ 1, 2, 3 ]) == [ 2, 3 ] + assert $ (A.drop 2 [ 1, 2, 3 ]) == [ 3 ] assert $ (A.drop 1 nil) == nil - log "dropWhile should remove all values that match a predicate from the front of an array" - assert $ (A.dropWhile (_ /= 1) [1, 2, 3]) == [1, 2, 3] - assert $ (A.dropWhile (_ /= 2) [1, 2, 3]) == [2, 3] + log + "dropWhile should remove all values that match a predicate from the front of an array" + assert $ (A.dropWhile (_ /= 1) [ 1, 2, 3 ]) == [ 1, 2, 3 ] + assert $ (A.dropWhile (_ /= 2) [ 1, 2, 3 ]) == [ 2, 3 ] assert $ (A.dropWhile (_ /= 1) nil) == nil - log "drop should remove the specified number of items from the end of an array" - assert $ (A.dropEnd 1 [1, 2, 3]) == [1, 2] - assert $ (A.dropEnd 2 [1, 2, 3]) == [1] + log + "drop should remove the specified number of items from the end of an array" + assert $ (A.dropEnd 1 [ 1, 2, 3 ]) == [ 1, 2 ] + assert $ (A.dropEnd 2 [ 1, 2, 3 ]) == [ 1 ] assert $ (A.dropEnd 1 nil) == nil log "take and drop should treat negative arguments as zero" - assert $ (A.take (-2) [1, 2, 3]) == nil - assert $ (A.drop (-2) [1, 2, 3]) == [1, 2, 3] + assert $ (A.take (-2) [ 1, 2, 3 ]) == nil + assert $ (A.drop (-2) [ 1, 2, 3 ]) == [ 1, 2, 3 ] log "span should split an array in two based on a predicate" - let testSpan { p, input, init_, rest_ } = do - let result = A.span p input - assert $ result.init == init_ - assert $ result.rest == rest_ + let + testSpan { p, input, init_, rest_ } = do + let result = A.span p input + assert $ result.init == init_ + assert $ result.rest == rest_ - let oneToSeven = [1, 2, 3, 4, 5, 6, 7] - testSpan { p: (_ < 4), input: oneToSeven, init_: [1, 2, 3], rest_: [4, 5, 6, 7] } + let oneToSeven = [ 1, 2, 3, 4, 5, 6, 7 ] + testSpan + { p: (_ < 4), input: oneToSeven, init_: [ 1, 2, 3 ], rest_: [ 4, 5, 6, 7 ] } log "span with all elements satisfying the predicate" testSpan { p: const true, input: oneToSeven, init_: oneToSeven, rest_: [] } @@ -363,8 +409,14 @@ testArray = do testSpan { p: const false, input: oneToSeven, init_: [], rest_: oneToSeven } log "span with large inputs: 10000" - let testBigSpan n = - testSpan { p: (_ < n), input: A.range 1 n, init_: A.range 1 (n-1), rest_: [n] } + let + testBigSpan n = + testSpan + { p: (_ < n) + , input: A.range 1 n + , init_: A.range 1 (n - 1) + , rest_: [ n ] + } testBigSpan 10000 log "span with large inputs: 40000" @@ -374,98 +426,120 @@ testArray = do testBigSpan 100000 log "group should group consecutive equal elements into arrays" - assert $ A.group [1, 2, 2, 3, 3, 3, 1] == [nea [1], nea [2, 2], nea [3, 3, 3], nea [1]] + assert $ A.group [ 1, 2, 2, 3, 3, 3, 1 ] == + [ nea [ 1 ], nea [ 2, 2 ], nea [ 3, 3, 3 ], nea [ 1 ] ] log "groupAll should group equal elements into arrays" - assert $ A.groupAll [1, 2, 2, 3, 3, 3, 1] == [nea [1, 1], nea [2, 2], nea [3, 3, 3]] + assert $ A.groupAll [ 1, 2, 2, 3, 3, 3, 1 ] == + [ nea [ 1, 1 ], nea [ 2, 2 ], nea [ 3, 3, 3 ] ] - log "groupBy should group consecutive equal elements into arrays based on an equivalence relation" - assert $ A.groupBy (\x y -> odd x && odd y) [1, 1, 2, 2, 3, 3] == [nea [1, 1], nea [2], nea [2], nea [3, 3]] + log + "groupBy should group consecutive equal elements into arrays based on an equivalence relation" + assert $ A.groupBy (\x y -> odd x && odd y) [ 1, 1, 2, 2, 3, 3 ] == + [ nea [ 1, 1 ], nea [ 2 ], nea [ 2 ], nea [ 3, 3 ] ] log "groupBy should be stable" - assert $ A.groupBy (\_ _ -> true) [1, 2, 3] == [nea [1, 2, 3]] + assert $ A.groupBy (\_ _ -> true) [ 1, 2, 3 ] == [ nea [ 1, 2, 3 ] ] - log "groupAllBy should group equal elements into arrays based on the result of a comparison function" - assert $ A.groupAllBy (comparing Down) [1, 3, 2, 4, 3, 3] == [nea [4], nea [3, 3, 3], nea [2], nea [1]] + log + "groupAllBy should group equal elements into arrays based on the result of a comparison function" + assert $ A.groupAllBy (comparing Down) [ 1, 3, 2, 4, 3, 3 ] == + [ nea [ 4 ], nea [ 3, 3, 3 ], nea [ 2 ], nea [ 1 ] ] log "groupAllBy should be stable" - assert $ A.groupAllBy (\_ _ -> EQ) [1, 2, 3] == [nea [1, 2, 3]] + assert $ A.groupAllBy (\_ _ -> EQ) [ 1, 2, 3 ] == [ nea [ 1, 2, 3 ] ] - log "nub should remove duplicate elements from the list, keeping the first occurence" - assert $ A.nub [1, 2, 2, 3, 4, 1] == [1, 2, 3, 4] + log + "nub should remove duplicate elements from the list, keeping the first occurence" + assert $ A.nub [ 1, 2, 2, 3, 4, 1 ] == [ 1, 2, 3, 4 ] log "nub should preserve order" - assert $ A.nub [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2] + assert $ A.nub [ 1, 3, 4, 2, 2, 1 ] == [ 1, 3, 4, 2 ] - log "nubEq should remove duplicate elements from the list, keeping the first occurence" - assert $ A.nubEq [1, 2, 2, 3, 4, 1] == [1, 2, 3, 4] + log + "nubEq should remove duplicate elements from the list, keeping the first occurence" + assert $ A.nubEq [ 1, 2, 2, 3, 4, 1 ] == [ 1, 2, 3, 4 ] log "nubEq should preserve order" - assert $ A.nubEq [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2] + assert $ A.nubEq [ 1, 3, 4, 2, 2, 1 ] == [ 1, 3, 4, 2 ] - log "nubBy should remove duplicate items from the list using a supplied predicate" - assert $ A.nubBy compare [1, 3, 4, 2, 2, 1] == [1, 3, 4, 2] + log + "nubBy should remove duplicate items from the list using a supplied predicate" + assert $ A.nubBy compare [ 1, 3, 4, 2, 2, 1 ] == [ 1, 3, 4, 2 ] - log "nubByEq should remove duplicate items from the list using a supplied predicate" + log + "nubByEq should remove duplicate items from the list using a supplied predicate" let nubPred = \x y -> if odd x then false else x == y - assert $ A.nubByEq nubPred [1, 2, 2, 3, 3, 4, 4, 1] == [1, 2, 3, 3, 4, 1] + assert $ A.nubByEq nubPred [ 1, 2, 2, 3, 3, 4, 4, 1 ] == [ 1, 2, 3, 3, 4, 1 ] log "union should produce the union of two arrays" - assert $ A.union [1, 2, 3] [2, 3, 4] == [1, 2, 3, 4] - assert $ A.union [1, 1, 2, 3] [2, 3, 4] == [1, 1, 2, 3, 4] + assert $ A.union [ 1, 2, 3 ] [ 2, 3, 4 ] == [ 1, 2, 3, 4 ] + assert $ A.union [ 1, 1, 2, 3 ] [ 2, 3, 4 ] == [ 1, 1, 2, 3, 4 ] - log "unionBy should produce the union of two arrays using the specified equality relation" - assert $ A.unionBy (\_ y -> y < 5) [1, 2, 3] [2, 3, 4, 5, 6] == [1, 2, 3, 5, 6] + log + "unionBy should produce the union of two arrays using the specified equality relation" + assert $ A.unionBy (\_ y -> y < 5) [ 1, 2, 3 ] [ 2, 3, 4, 5, 6 ] == + [ 1, 2, 3, 5, 6 ] log "delete should remove the first matching item from an array" - assert $ A.delete 1 [1, 2, 1] == [2, 1] - assert $ A.delete 2 [1, 2, 1] == [1, 1] + assert $ A.delete 1 [ 1, 2, 1 ] == [ 2, 1 ] + assert $ A.delete 2 [ 1, 2, 1 ] == [ 1, 1 ] - log "deleteBy should remove the first equality-relation-matching item from an array" - assert $ A.deleteBy (/=) 2 [1, 2, 1] == [2, 1] - assert $ A.deleteBy (/=) 1 [1, 2, 1] == [1, 1] + log + "deleteBy should remove the first equality-relation-matching item from an array" + assert $ A.deleteBy (/=) 2 [ 1, 2, 1 ] == [ 2, 1 ] + assert $ A.deleteBy (/=) 1 [ 1, 2, 1 ] == [ 1, 1 ] log "(\\\\) should return the difference between two lists" - assert $ [1, 2, 3, 4, 3, 2, 1] \\ [1, 1, 2, 3] == [4, 3, 2] + assert $ [ 1, 2, 3, 4, 3, 2, 1 ] \\ [ 1, 1, 2, 3 ] == [ 4, 3, 2 ] log "intersect should return the intersection of two arrays" - assert $ A.intersect [1, 2, 3, 4, 3, 2, 1] [1, 1, 2, 3] == [1, 2, 3, 3, 2, 1] + assert $ A.intersect [ 1, 2, 3, 4, 3, 2, 1 ] [ 1, 1, 2, 3 ] == + [ 1, 2, 3, 3, 2, 1 ] - log "intersectBy should return the intersection of two arrays using the specified equivalence relation" - assert $ A.intersectBy (\x y -> (x * 2) == y) [1, 2, 3] [2, 6] == [1, 3] + log + "intersectBy should return the intersection of two arrays using the specified equivalence relation" + assert $ A.intersectBy (\x y -> (x * 2) == y) [ 1, 2, 3 ] [ 2, 6 ] == [ 1, 3 ] log "zipWith should use the specified function to zip two lists together" - assert $ A.zipWith (\x y -> [show x, y]) [1, 2, 3] ["a", "b", "c"] == [["1", "a"], ["2", "b"], ["3", "c"]] + assert $ A.zipWith (\x y -> [ show x, y ]) [ 1, 2, 3 ] [ "a", "b", "c" ] == + [ [ "1", "a" ], [ "2", "b" ], [ "3", "c" ] ] log "zipWithA should use the specified function to zip two lists together" - assert $ A.zipWithA (\x y -> Just $ Tuple x y) [1, 2, 3] ["a", "b", "c"] == Just [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] + assert $ A.zipWithA (\x y -> Just $ Tuple x y) [ 1, 2, 3 ] [ "a", "b", "c" ] + == Just [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] log "zip should use the specified function to zip two lists together" - assert $ A.zip [1, 2, 3] ["a", "b", "c"] == [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] + assert $ A.zip [ 1, 2, 3 ] [ "a", "b", "c" ] == + [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] log "unzip should deconstruct a list of tuples into a tuple of lists" - assert $ A.unzip [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] == Tuple [1, 2, 3] ["a", "b", "c"] + assert $ A.unzip [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] == Tuple + [ 1, 2, 3 ] + [ "a", "b", "c" ] - log "any should return true if at least one array element satisfy the given predicate" + log + "any should return true if at least one array element satisfy the given predicate" assert $ not $ A.any (_ > 0) [] - assert $ A.any (_ > 0) [-1, 0, 1] - assert $ not $ A.any (_ > 0) [-1, -2, -3] + assert $ A.any (_ > 0) [ -1, 0, 1 ] + assert $ not $ A.any (_ > 0) [ -1, -2, -3 ] - log "all should return true if all the array elements satisfy the given predicate" + log + "all should return true if all the array elements satisfy the given predicate" assert $ A.all (_ > 0) [] - assert $ A.all (_ > 0) [1, 2, 3] - assert $ not $ A.all (_ > 0) [-1, -2, -3] + assert $ A.all (_ > 0) [ 1, 2, 3 ] + assert $ not $ A.all (_ > 0) [ -1, -2, -3 ] log "foldM should perform a fold using a monadic step function" assert $ A.foldM (\x y -> Just (x + y)) 0 (A.range 1 10) == Just 55 assert $ A.foldM (\_ _ -> Nothing) 0 (A.range 1 10) == Nothing log "fromFoldable" - for_ [[], [1], [1,2], [1,2,3,4,5]] \xs -> do + for_ [ [], [ 1 ], [ 1, 2 ], [ 1, 2, 3, 4, 5 ] ] \xs -> do assert $ A.fromFoldable xs == xs log "fromFoldable is stack safe" - for_ [1, 1000, 10000, 20000, 50000] \n -> do + for_ [ 1, 1000, 10000, 20000, 50000 ] \n -> do let elem = 0 let arr = A.fromFoldable (Replicated n elem) assert $ A.length arr == n @@ -475,10 +549,10 @@ testArray = do let toUnfoldableId xs = A.toUnfoldable xs == xs traverse_ (assert <<< toUnfoldableId) [ [] - , [1] - , [1,2,3] - , [2,3,1] - , [4,0,0,1,25,36,458,5842,23757] + , [ 1 ] + , [ 1, 2, 3 ] + , [ 2, 3, 1 ] + , [ 4, 0, 0, 1, 25, 36, 458, 5842, 23757 ] ] nea :: Array ~> NEA.NonEmptyArray @@ -491,7 +565,7 @@ odd :: Int -> Boolean odd n = n `mod` 2 /= zero doubleAndOrig :: Int -> Array Int -doubleAndOrig x = [x * 2, x] +doubleAndOrig x = [ x * 2, x ] data Replicated a = Replicated Int a @@ -502,5 +576,5 @@ instance foldableReplicated :: Foldable Replicated where applyN :: forall a. Int -> (a -> a) -> a -> a applyN n f x - | n <= 0 = x + | n <= 0 = x | otherwise = applyN (n - 1) f (f x) diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index 0ee98550..1017dfae 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -23,353 +23,471 @@ import Test.Data.UndefinedOr (defined, undefined) testNonEmptyArray :: Effect Unit testNonEmptyArray = do - let fromArray :: forall a. Array a -> NEA.NonEmptyArray a - fromArray = unsafePartial fromJust <<< NEA.fromArray + let + fromArray :: forall a. Array a -> NEA.NonEmptyArray a + fromArray = unsafePartial fromJust <<< NEA.fromArray - nea :: forall a. Array a -> NEA.NonEmptyArray a - nea = fromArray + nea :: forall a. Array a -> NEA.NonEmptyArray a + nea = fromArray log "singleton should construct an array with a single value" - assert $ NEA.toArray (NEA.singleton 1) == [1] - assert $ NEA.toArray (NEA.singleton "foo") == ["foo"] - - log "range should create an inclusive array of integers for the specified start and end" - assert $ NEA.toArray (NEA.range 0 5) == [0, 1, 2, 3, 4, 5] - assert $ NEA.toArray (NEA.range 2 (-3)) == [2, 1, 0, -1, -2, -3] - assert $ NEA.toArray (NEA.range 0 0) == [0] - - log "replicate should produce an array containg an item a specified number of times" - assert $ NEA.toArray (NEA.replicate 3 true) == [true, true, true] - assert $ NEA.toArray (NEA.replicate 1 "foo") == ["foo"] - assert $ NEA.toArray (NEA.replicate 0 "foo") == ["foo"] - assert $ NEA.toArray (NEA.replicate (-1) "foo") == ["foo"] + assert $ NEA.toArray (NEA.singleton 1) == [ 1 ] + assert $ NEA.toArray (NEA.singleton "foo") == [ "foo" ] + + log + "range should create an inclusive array of integers for the specified start and end" + assert $ NEA.toArray (NEA.range 0 5) == [ 0, 1, 2, 3, 4, 5 ] + assert $ NEA.toArray (NEA.range 2 (-3)) == [ 2, 1, 0, -1, -2, -3 ] + assert $ NEA.toArray (NEA.range 0 0) == [ 0 ] + + log + "replicate should produce an array containg an item a specified number of times" + assert $ NEA.toArray (NEA.replicate 3 true) == [ true, true, true ] + assert $ NEA.toArray (NEA.replicate 1 "foo") == [ "foo" ] + assert $ NEA.toArray (NEA.replicate 0 "foo") == [ "foo" ] + assert $ NEA.toArray (NEA.replicate (-1) "foo") == [ "foo" ] log "length should return the number of items in an array" assert $ NEA.length (NEA.singleton 1) == 1 - assert $ NEA.length (fromArray [1, 2, 3, 4, 5]) == 5 + assert $ NEA.length (fromArray [ 1, 2, 3, 4, 5 ]) == 5 log "cons should add an item to the start of an array" - assert $ NEA.cons 4 (fromArray [1, 2, 3]) == fromArray [4, 1, 2, 3] - assert $ NEA.cons' 4 [1, 2, 3] == fromArray [4, 1, 2, 3] + assert $ NEA.cons 4 (fromArray [ 1, 2, 3 ]) == fromArray [ 4, 1, 2, 3 ] + assert $ NEA.cons' 4 [ 1, 2, 3 ] == fromArray [ 4, 1, 2, 3 ] log "snoc should add an item to the end of an array" - assert $ fromArray [1, 2, 3] `NEA.snoc` 4 == fromArray [1, 2, 3, 4] - assert $ [1, 2, 3] `NEA.snoc'` 4 == fromArray [1, 2, 3, 4] + assert $ fromArray [ 1, 2, 3 ] `NEA.snoc` 4 == fromArray [ 1, 2, 3, 4 ] + assert $ [ 1, 2, 3 ] `NEA.snoc'` 4 == fromArray [ 1, 2, 3, 4 ] log "insert should add an item at the appropriate place in a sorted array" - assert $ NEA.insert 1.5 (fromArray [1.0, 2.0, 3.0]) - == fromArray [1.0, 1.5, 2.0, 3.0] - assert $ NEA.insert 4 (fromArray [1, 2, 3]) == fromArray [1, 2, 3, 4] + assert $ NEA.insert 1.5 (fromArray [ 1.0, 2.0, 3.0 ]) + == fromArray [ 1.0, 1.5, 2.0, 3.0 ] + assert $ NEA.insert 4 (fromArray [ 1, 2, 3 ]) == fromArray [ 1, 2, 3, 4 ] - log "insertBy should add an item at the appropriate place in a sorted array using the specified comparison" - assert $ NEA.insertBy (flip compare) 1.5 (fromArray [1.0, 2.0, 3.0]) - == fromArray [1.0, 2.0, 3.0, 1.5] + log + "insertBy should add an item at the appropriate place in a sorted array using the specified comparison" + assert $ NEA.insertBy (flip compare) 1.5 (fromArray [ 1.0, 2.0, 3.0 ]) + == fromArray [ 1.0, 2.0, 3.0, 1.5 ] log "head should return the first value of a non-empty array" - assert $ NEA.head (fromArray ["foo", "bar"]) == "foo" + assert $ NEA.head (fromArray [ "foo", "bar" ]) == "foo" log "last should return the last value of a non-empty array" - assert $ NEA.last (fromArray ["foo", "bar"]) == "bar" + assert $ NEA.last (fromArray [ "foo", "bar" ]) == "bar" - log "tail should return an array containing all the items in an array apart from the first for a non-empty array" - assert $ NEA.tail (fromArray ["foo", "bar", "baz"]) == ["bar", "baz"] + log + "tail should return an array containing all the items in an array apart from the first for a non-empty array" + assert $ NEA.tail (fromArray [ "foo", "bar", "baz" ]) == [ "bar", "baz" ] - log "init should return an array containing all the items in an array apart from the first for a non-empty array" - assert $ NEA.init (fromArray ["foo", "bar", "baz"]) == ["foo", "bar"] + log + "init should return an array containing all the items in an array apart from the first for a non-empty array" + assert $ NEA.init (fromArray [ "foo", "bar", "baz" ]) == [ "foo", "bar" ] log "uncons should split an array into a head and tail record" let u1 = NEA.uncons $ NEA.singleton 1 assert $ u1.head == 1 assert $ u1.tail == [] - let u2 = NEA.uncons $ fromArray [1, 2, 3] + let u2 = NEA.uncons $ fromArray [ 1, 2, 3 ] assert $ u2.head == 1 - assert $ u2.tail == [2, 3] + assert $ u2.tail == [ 2, 3 ] log "unsnoc should split an array into an init and last record" let u3 = NEA.unsnoc $ NEA.singleton 1 assert $ u3.init == [] assert $ u3.last == 1 - let u4 = NEA.unsnoc $ fromArray [1, 2, 3] - assert $ u4.init == [1, 2] + let u4 = NEA.unsnoc $ fromArray [ 1, 2, 3 ] + assert $ u4.init == [ 1, 2 ] assert $ u4.last == 3 - log "index should return Just x when the index is within the bounds of the array" - assert $ NEA.index (fromArray [1, 2, 3]) 0 == Just 1 - assert $ NEA.index (fromArray [1, 2, 3]) 1 == Just 2 - assert $ NEA.index (fromArray [1, 2, 3]) 2 == Just 3 + log + "index should return Just x when the index is within the bounds of the array" + assert $ NEA.index (fromArray [ 1, 2, 3 ]) 0 == Just 1 + assert $ NEA.index (fromArray [ 1, 2, 3 ]) 1 == Just 2 + assert $ NEA.index (fromArray [ 1, 2, 3 ]) 2 == Just 3 - log "index should return Nothing when the index is outside of the bounds of the array" - assert $ NEA.index (fromArray [1, 2, 3]) 6 == Nothing - assert $ NEA.index (fromArray [1, 2, 3]) (-1) == Nothing + log + "index should return Nothing when the index is outside of the bounds of the array" + assert $ NEA.index (fromArray [ 1, 2, 3 ]) 6 == Nothing + assert $ NEA.index (fromArray [ 1, 2, 3 ]) (-1) == Nothing - log "elem should return true if the array contains the given element at least once" - assert $ NEA.elem 1 (fromArray [1, 2, 1]) == true - assert $ NEA.elem 4 (fromArray [1, 2, 1]) == false + log + "elem should return true if the array contains the given element at least once" + assert $ NEA.elem 1 (fromArray [ 1, 2, 1 ]) == true + assert $ NEA.elem 4 (fromArray [ 1, 2, 1 ]) == false - log "notElem should return true if the array does not contain the given element" - assert $ NEA.notElem 1 (fromArray [1, 2, 1]) == false - assert $ NEA.notElem 4 (fromArray [1, 2, 1]) == true + log + "notElem should return true if the array does not contain the given element" + assert $ NEA.notElem 1 (fromArray [ 1, 2, 1 ]) == false + assert $ NEA.notElem 4 (fromArray [ 1, 2, 1 ]) == true - log "elemIndex should return the index of an item that a predicate returns true for in an array" - assert $ NEA.elemIndex 1 (fromArray [1, 2, 1]) == Just 0 - assert $ NEA.elemIndex 4 (fromArray [1, 2, 1]) == Nothing + log + "elemIndex should return the index of an item that a predicate returns true for in an array" + assert $ NEA.elemIndex 1 (fromArray [ 1, 2, 1 ]) == Just 0 + assert $ NEA.elemIndex 4 (fromArray [ 1, 2, 1 ]) == Nothing log "elemLastIndex should return the last index of an item in an array" - assert $ NEA.elemLastIndex 1 (fromArray [1, 2, 1]) == Just 2 - assert $ NEA.elemLastIndex 4 (fromArray [1, 2, 1]) == Nothing - - log "find should return the first element for which a predicate returns true in an array" - assert $ NEA.find (_ == 1) (fromArray [1, 2, 1]) == Just 1 - assert $ NEA.find (_ == 3) (fromArray [1, 2, 1]) == Nothing - - log "findMap should return the mapping of the first element that satisfies the given predicate" - assert $ NEA.findMap (\x -> if x > 3 then Just x else Nothing) (fromArray [1, 2, 4]) == Just 4 - assert $ NEA.findMap (\x -> if x > 3 then Just x else Nothing) (fromArray [1, 2, 1]) == Nothing - assert $ NEA.findMap (\x -> if x > 3 then Just x else Nothing) (fromArray [4, 1, 5]) == Just 4 - - log "findIndex should return the index of an item that a predicate returns true for in an array" - assert $ (NEA.findIndex (_ /= 1) (fromArray [1, 2, 1])) == Just 1 - assert $ (NEA.findIndex (_ == 3) (fromArray [1, 2, 1])) == Nothing + assert $ NEA.elemLastIndex 1 (fromArray [ 1, 2, 1 ]) == Just 2 + assert $ NEA.elemLastIndex 4 (fromArray [ 1, 2, 1 ]) == Nothing + + log + "find should return the first element for which a predicate returns true in an array" + assert $ NEA.find (_ == 1) (fromArray [ 1, 2, 1 ]) == Just 1 + assert $ NEA.find (_ == 3) (fromArray [ 1, 2, 1 ]) == Nothing + + log + "findMap should return the mapping of the first element that satisfies the given predicate" + assert $ + NEA.findMap (\x -> if x > 3 then Just x else Nothing) + (fromArray [ 1, 2, 4 ]) == Just 4 + assert $ + NEA.findMap (\x -> if x > 3 then Just x else Nothing) + (fromArray [ 1, 2, 1 ]) == Nothing + assert $ + NEA.findMap (\x -> if x > 3 then Just x else Nothing) + (fromArray [ 4, 1, 5 ]) == Just 4 + + log + "findIndex should return the index of an item that a predicate returns true for in an array" + assert $ (NEA.findIndex (_ /= 1) (fromArray [ 1, 2, 1 ])) == Just 1 + assert $ (NEA.findIndex (_ == 3) (fromArray [ 1, 2, 1 ])) == Nothing log "findLastIndex should return the last index of an item in an array" - assert $ (NEA.findLastIndex (_ /= 1) (fromArray [2, 1, 2])) == Just 2 - assert $ (NEA.findLastIndex (_ == 3) (fromArray [2, 1, 2])) == Nothing + assert $ (NEA.findLastIndex (_ /= 1) (fromArray [ 2, 1, 2 ])) == Just 2 + assert $ (NEA.findLastIndex (_ == 3) (fromArray [ 2, 1, 2 ])) == Nothing log "insertAt should add an item at the specified index" - assert $ NEA.insertAt 0 1 (fromArray [2, 3]) == Just (fromArray [1, 2, 3]) - assert $ NEA.insertAt 1 1 (fromArray [2, 3]) == Just (fromArray [2, 1, 3]) - assert $ NEA.insertAt 2 1 (fromArray [2, 3]) == Just (fromArray [2, 3, 1]) + assert $ NEA.insertAt 0 1 (fromArray [ 2, 3 ]) == Just (fromArray [ 1, 2, 3 ]) + assert $ NEA.insertAt 1 1 (fromArray [ 2, 3 ]) == Just (fromArray [ 2, 1, 3 ]) + assert $ NEA.insertAt 2 1 (fromArray [ 2, 3 ]) == Just (fromArray [ 2, 3, 1 ]) log "insertAt should return Nothing if the index is out of A.range" assert $ (NEA.insertAt 2 1 (NEA.singleton 1)) == Nothing log "deleteAt should remove an item at the specified index" - assert $ (NEA.deleteAt 0 (fromArray [1, 2, 3])) == Just [2, 3] - assert $ (NEA.deleteAt 1 (fromArray [1, 2, 3])) == Just [1, 3] + assert $ (NEA.deleteAt 0 (fromArray [ 1, 2, 3 ])) == Just [ 2, 3 ] + assert $ (NEA.deleteAt 1 (fromArray [ 1, 2, 3 ])) == Just [ 1, 3 ] log "deleteAt should return Nothing if the index is out of A.range" assert $ (NEA.deleteAt 1 (NEA.singleton 1)) == Nothing log "updateAt should replace an item at the specified index" - assert $ NEA.updateAt 0 9 (fromArray [1, 2, 3]) == Just (fromArray [9, 2, 3]) - assert $ NEA.updateAt 1 9 (fromArray [1, 2, 3]) == Just (fromArray [1, 9, 3]) + assert $ NEA.updateAt 0 9 (fromArray [ 1, 2, 3 ]) == Just + (fromArray [ 9, 2, 3 ]) + assert $ NEA.updateAt 1 9 (fromArray [ 1, 2, 3 ]) == Just + (fromArray [ 1, 9, 3 ]) log "updateAt should return Nothing if the index is out of A.range" assert $ NEA.updateAt 1 9 (NEA.singleton 0) == Nothing log "modifyAt should update an item at the specified index" - assert $ NEA.modifyAt 0 (_ + 1) (fromArray [1, 2, 3]) == Just (fromArray [2, 2, 3]) - assert $ NEA.modifyAt 1 (_ + 1) (fromArray [1, 2, 3]) == Just (fromArray [1, 3, 3]) + assert $ NEA.modifyAt 0 (_ + 1) (fromArray [ 1, 2, 3 ]) == Just + (fromArray [ 2, 2, 3 ]) + assert $ NEA.modifyAt 1 (_ + 1) (fromArray [ 1, 2, 3 ]) == Just + (fromArray [ 1, 3, 3 ]) log "modifyAt should return Nothing if the index is out of A.range" assert $ NEA.modifyAt 1 (_ + 1) (NEA.singleton 0) == Nothing - log "alterAt should update an item at the specified index when the function returns Just" - assert $ NEA.alterAt 0 (Just <<< (_ + 1)) (fromArray [1, 2, 3]) == Just [2, 2, 3] - assert $ NEA.alterAt 1 (Just <<< (_ + 1)) (fromArray [1, 2, 3]) == Just [1, 3, 3] + log + "alterAt should update an item at the specified index when the function returns Just" + assert $ NEA.alterAt 0 (Just <<< (_ + 1)) (fromArray [ 1, 2, 3 ]) == Just + [ 2, 2, 3 ] + assert $ NEA.alterAt 1 (Just <<< (_ + 1)) (fromArray [ 1, 2, 3 ]) == Just + [ 1, 3, 3 ] - log "alterAt should drop an item at the specified index when the function returns Nothing" - assert $ NEA.alterAt 0 (const Nothing) (fromArray [1, 2, 3]) == Just [2, 3] - assert $ NEA.alterAt 1 (const Nothing) (fromArray [1, 2, 3]) == Just [1, 3] + log + "alterAt should drop an item at the specified index when the function returns Nothing" + assert $ NEA.alterAt 0 (const Nothing) (fromArray [ 1, 2, 3 ]) == Just + [ 2, 3 ] + assert $ NEA.alterAt 1 (const Nothing) (fromArray [ 1, 2, 3 ]) == Just + [ 1, 3 ] log "alterAt should return Nothing if the index is out of NEA.range" assert $ NEA.alterAt 1 (Just <<< (_ + 1)) (NEA.singleton 1) == Nothing - log "intersperse should return the original array when given an array with one element" + log + "intersperse should return the original array when given an array with one element" assert $ NEA.intersperse " " (NEA.singleton "a") == NEA.singleton "a" - log "intersperse should insert the given element in-between each element in an array with two or more elements" - assert $ NEA.intersperse " " (fromArray ["a", "b"]) == fromArray ["a", " ", "b"] - assert $ NEA.intersperse 0 (fromArray [ 1, 2, 3, 4, 5 ]) == fromArray [ 1, 0, 2, 0, 3, 0, 4, 0, 5 ] + log + "intersperse should insert the given element in-between each element in an array with two or more elements" + assert $ NEA.intersperse " " (fromArray [ "a", "b" ]) == fromArray + [ "a", " ", "b" ] + assert $ NEA.intersperse 0 (fromArray [ 1, 2, 3, 4, 5 ]) == fromArray + [ 1, 0, 2, 0, 3, 0, 4, 0, 5 ] log "reverse should reverse the order of items in an array" - assert $ NEA.reverse (fromArray [1, 2, 3]) == fromArray [3, 2, 1] + assert $ NEA.reverse (fromArray [ 1, 2, 3 ]) == fromArray [ 3, 2, 1 ] assert $ NEA.reverse (NEA.singleton 0) == NEA.singleton 0 log "concat should join an array of arrays" - assert $ NEA.concat (fromArray [fromArray [1, 2], fromArray [3, 4]]) == fromArray [1, 2, 3, 4] + assert $ NEA.concat (fromArray [ fromArray [ 1, 2 ], fromArray [ 3, 4 ] ]) == + fromArray [ 1, 2, 3, 4 ] log "concatMap should be equivalent to (concat <<< map)" - assert $ NEA.concatMap doubleAndOrig (fromArray [1, 2, 3]) == NEA.concat (map doubleAndOrig (fromArray [1, 2, 3])) + assert $ NEA.concatMap doubleAndOrig (fromArray [ 1, 2, 3 ]) == NEA.concat + (map doubleAndOrig (fromArray [ 1, 2, 3 ])) log "filter should remove items that don't match a predicate" - assert $ NEA.filter odd (NEA.range 0 10) == [1, 3, 5, 7, 9] + assert $ NEA.filter odd (NEA.range 0 10) == [ 1, 3, 5, 7, 9 ] log "splitAt should split the array at the given number of elements" - assert $ NEA.splitAt 3 (fromArray [1, 2, 3, 4, 5]) == { before: [1, 2, 3], after: [4, 5] } - assert $ NEA.splitAt 1 (fromArray [1, 2, 3]) == { before: [1], after: [2, 3] } - assert $ NEA.splitAt 3 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] } - assert $ NEA.splitAt 4 (fromArray [1, 2, 3]) == { before: [1, 2, 3], after: [] } - assert $ NEA.splitAt 0 (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] } - assert $ NEA.splitAt (-1) (fromArray [1, 2, 3]) == { before: [], after: [1, 2, 3] } - - log "filterA should remove items that don't match a predicate while using an applicative behaviour" - assert $ NEA.filterA (Just <<< odd) (NEA.range 0 10) == Just [1, 3, 5, 7, 9] + assert $ NEA.splitAt 3 (fromArray [ 1, 2, 3, 4, 5 ]) == + { before: [ 1, 2, 3 ], after: [ 4, 5 ] } + assert $ NEA.splitAt 1 (fromArray [ 1, 2, 3 ]) == + { before: [ 1 ], after: [ 2, 3 ] } + assert $ NEA.splitAt 3 (fromArray [ 1, 2, 3 ]) == + { before: [ 1, 2, 3 ], after: [] } + assert $ NEA.splitAt 4 (fromArray [ 1, 2, 3 ]) == + { before: [ 1, 2, 3 ], after: [] } + assert $ NEA.splitAt 0 (fromArray [ 1, 2, 3 ]) == + { before: [], after: [ 1, 2, 3 ] } + assert $ NEA.splitAt (-1) (fromArray [ 1, 2, 3 ]) == + { before: [], after: [ 1, 2, 3 ] } + + log + "filterA should remove items that don't match a predicate while using an applicative behaviour" + assert $ NEA.filterA (Just <<< odd) (NEA.range 0 10) == Just [ 1, 3, 5, 7, 9 ] assert $ NEA.filterA (const Nothing) (NEA.range 0 10) == Nothing log "filterA should apply effects in the right order" assert $ NEA.filterA (Const <<< show) (NEA.range 1 5) == Const "12345" - log "mapMaybe should transform every item in an array, throwing out Nothing values" - assert $ NEA.mapMaybe (\x -> if x /= 0 then Just x else Nothing) (fromArray [0, 1, 0, 0, 2, 3]) == [1, 2, 3] + log + "mapMaybe should transform every item in an array, throwing out Nothing values" + assert $ + NEA.mapMaybe (\x -> if x /= 0 then Just x else Nothing) + (fromArray [ 0, 1, 0, 0, 2, 3 ]) == [ 1, 2, 3 ] log "catMaybe should take an array of Maybe values and throw out Nothings" - assert $ NEA.catMaybes (fromArray [Nothing, Just 2, Nothing, Just 4]) == [2, 4] + assert $ NEA.catMaybes (fromArray [ Nothing, Just 2, Nothing, Just 4 ]) == + [ 2, 4 ] log "mapWithIndex applies a function with an index for every element" - assert $ NEA.mapWithIndex (\i x -> x - i) (fromArray [9,8,7,6,5]) == fromArray [9,7,5,3,1] + assert $ NEA.mapWithIndex (\i x -> x - i) (fromArray [ 9, 8, 7, 6, 5 ]) == + fromArray [ 9, 7, 5, 3, 1 ] - log "scanl should return an array that stores the accumulated value at each step" - assert $ NEA.scanl (+) 0 (fromArray [1,2,3]) == fromArray [1, 3, 6] - assert $ NEA.scanl (-) 10 (fromArray [1,2,3]) == fromArray [9, 7, 4] + log + "scanl should return an array that stores the accumulated value at each step" + assert $ NEA.scanl (+) 0 (fromArray [ 1, 2, 3 ]) == fromArray [ 1, 3, 6 ] + assert $ NEA.scanl (-) 10 (fromArray [ 1, 2, 3 ]) == fromArray [ 9, 7, 4 ] log "scanl should return the same results as its Foldable counterpart" - assert $ NEA.scanl (+) 0 (fromArray [1,2,3]) == scanl (+) 0 (fromArray [1,2,3]) - assert $ NEA.scanl (-) 10 (fromArray [1,2,3]) == scanl (-) 10 (fromArray [1,2,3]) + assert $ NEA.scanl (+) 0 (fromArray [ 1, 2, 3 ]) == scanl (+) 0 + (fromArray [ 1, 2, 3 ]) + assert $ NEA.scanl (-) 10 (fromArray [ 1, 2, 3 ]) == scanl (-) 10 + (fromArray [ 1, 2, 3 ]) - log "scanr should return an array that stores the accumulated value at each step" - assert $ NEA.scanr (+) 0 (fromArray [1,2,3]) == fromArray [6,5,3] - assert $ NEA.scanr (flip (-)) 10 (fromArray [1,2,3]) == fromArray [4,5,7] + log + "scanr should return an array that stores the accumulated value at each step" + assert $ NEA.scanr (+) 0 (fromArray [ 1, 2, 3 ]) == fromArray [ 6, 5, 3 ] + assert $ NEA.scanr (flip (-)) 10 (fromArray [ 1, 2, 3 ]) == fromArray + [ 4, 5, 7 ] log "scanr should return the same results as its Foldable counterpart" - assert $ NEA.scanr (+) 0 (fromArray [1,2,3]) == scanr (+) 0 (fromArray [1,2,3]) - assert $ NEA.scanr (flip (-)) 10 (fromArray [1,2,3]) == scanr (flip (-)) 10 (fromArray [1,2,3]) + assert $ NEA.scanr (+) 0 (fromArray [ 1, 2, 3 ]) == scanr (+) 0 + (fromArray [ 1, 2, 3 ]) + assert $ NEA.scanr (flip (-)) 10 (fromArray [ 1, 2, 3 ]) == scanr (flip (-)) + 10 + (fromArray [ 1, 2, 3 ]) log "updateAtIndices changes the elements at specified indices" - assert $ NEA.updateAtIndices - [Tuple 0 false, Tuple 2 false, Tuple 8 false] - (fromArray [true, true, true, true]) == - fromArray [false, true, false, true] + assert $ + NEA.updateAtIndices + [ Tuple 0 false, Tuple 2 false, Tuple 8 false ] + (fromArray [ true, true, true, true ]) == + fromArray [ false, true, false, true ] log "modifyAtIndices modifies the elements at specified indices" - assert $ NEA.modifyAtIndices [0, 2, 8] not (fromArray [true, true, true, true]) == - (fromArray [false, true, false, true]) - - log "sort should reorder a list into ascending order based on the result of compare" - assert $ NEA.sort (fromArray [1, 3, 2, 5, 6, 4]) == fromArray [1, 2, 3, 4, 5, 6] - assert $ NEA.sort (fromArray [defined 1, undefined, defined 2]) == fromArray [undefined, defined 1, defined 2] - - log "sortBy should reorder a list into ascending order based on the result of a comparison function" - assert $ NEA.sortBy (flip compare) (fromArray [1, 3, 2, 5, 6, 4]) == fromArray [6, 5, 4, 3, 2, 1] - - log "sortWith should reorder a list into ascending order based on the result of compare over a projection" - assert $ NEA.sortWith identity (fromArray [1, 3, 2, 5, 6, 4]) == fromArray [1, 2, 3, 4, 5, 6] - - log "take should keep the specified number of items from the front of an array, discarding the rest" - assert $ NEA.take 1 (fromArray [1, 2, 3]) == [1] - assert $ NEA.take 2 (fromArray [1, 2, 3]) == [1, 2] - - log "takeWhile should keep all values that match a predicate from the front of an array" - assert $ NEA.takeWhile (_ /= 2) (fromArray [1, 2, 3]) == [1] - assert $ NEA.takeWhile (_ /= 3) (fromArray [1, 2, 3]) == [1, 2] - - log "take should keep the specified number of items from the end of an array, discarding the rest" - assert $ NEA.takeEnd 1 (fromArray [1, 2, 3]) == [3] - assert $ NEA.takeEnd 2 (fromArray [1, 2, 3]) == [2, 3] - - log "drop should remove the specified number of items from the front of an array" - assert $ NEA.drop 1 (fromArray [1, 2, 3]) == [2, 3] - assert $ NEA.drop 2 (fromArray [1, 2, 3]) == [3] - - log "dropWhile should remove all values that match a predicate from the front of an array" - assert $ NEA.dropWhile (_ /= 1) (fromArray [1, 2, 3]) == [1, 2, 3] - assert $ NEA.dropWhile (_ /= 2) (fromArray [1, 2, 3]) == [2, 3] - - log "drop should remove the specified number of items from the end of an array" - assert $ NEA.dropEnd 1 (fromArray [1, 2, 3]) == [1, 2] - assert $ NEA.dropEnd 2 (fromArray [1, 2, 3]) == [1] + assert $ + NEA.modifyAtIndices [ 0, 2, 8 ] not (fromArray [ true, true, true, true ]) + == + (fromArray [ false, true, false, true ]) + + log + "sort should reorder a list into ascending order based on the result of compare" + assert $ NEA.sort (fromArray [ 1, 3, 2, 5, 6, 4 ]) == fromArray + [ 1, 2, 3, 4, 5, 6 ] + assert $ NEA.sort (fromArray [ defined 1, undefined, defined 2 ]) == fromArray + [ undefined, defined 1, defined 2 ] + + log + "sortBy should reorder a list into ascending order based on the result of a comparison function" + assert $ NEA.sortBy (flip compare) (fromArray [ 1, 3, 2, 5, 6, 4 ]) == + fromArray [ 6, 5, 4, 3, 2, 1 ] + + log + "sortWith should reorder a list into ascending order based on the result of compare over a projection" + assert $ NEA.sortWith identity (fromArray [ 1, 3, 2, 5, 6, 4 ]) == fromArray + [ 1, 2, 3, 4, 5, 6 ] + + log + "take should keep the specified number of items from the front of an array, discarding the rest" + assert $ NEA.take 1 (fromArray [ 1, 2, 3 ]) == [ 1 ] + assert $ NEA.take 2 (fromArray [ 1, 2, 3 ]) == [ 1, 2 ] + + log + "takeWhile should keep all values that match a predicate from the front of an array" + assert $ NEA.takeWhile (_ /= 2) (fromArray [ 1, 2, 3 ]) == [ 1 ] + assert $ NEA.takeWhile (_ /= 3) (fromArray [ 1, 2, 3 ]) == [ 1, 2 ] + + log + "take should keep the specified number of items from the end of an array, discarding the rest" + assert $ NEA.takeEnd 1 (fromArray [ 1, 2, 3 ]) == [ 3 ] + assert $ NEA.takeEnd 2 (fromArray [ 1, 2, 3 ]) == [ 2, 3 ] + + log + "drop should remove the specified number of items from the front of an array" + assert $ NEA.drop 1 (fromArray [ 1, 2, 3 ]) == [ 2, 3 ] + assert $ NEA.drop 2 (fromArray [ 1, 2, 3 ]) == [ 3 ] + + log + "dropWhile should remove all values that match a predicate from the front of an array" + assert $ NEA.dropWhile (_ /= 1) (fromArray [ 1, 2, 3 ]) == [ 1, 2, 3 ] + assert $ NEA.dropWhile (_ /= 2) (fromArray [ 1, 2, 3 ]) == [ 2, 3 ] + + log + "drop should remove the specified number of items from the end of an array" + assert $ NEA.dropEnd 1 (fromArray [ 1, 2, 3 ]) == [ 1, 2 ] + assert $ NEA.dropEnd 2 (fromArray [ 1, 2, 3 ]) == [ 1 ] log "span should split an array in two based on a predicate" - let testSpan { p, input, init_, rest_ } = do - let result = NEA.span p input - assert $ result.init == init_ - assert $ result.rest == rest_ + let + testSpan { p, input, init_, rest_ } = do + let result = NEA.span p input + assert $ result.init == init_ + assert $ result.rest == rest_ - let oneToSeven = fromArray [1, 2, 3, 4, 5, 6, 7] - testSpan { p: (_ < 4), input: oneToSeven, init_: [1, 2, 3], rest_: [4, 5, 6, 7] } + let oneToSeven = fromArray [ 1, 2, 3, 4, 5, 6, 7 ] + testSpan + { p: (_ < 4), input: oneToSeven, init_: [ 1, 2, 3 ], rest_: [ 4, 5, 6, 7 ] } log "group should group consecutive equal elements into arrays" - assert $ NEA.group (fromArray [1, 2, 2, 3, 3, 3, 1]) == fromArray [NEA.singleton 1, fromArray [2, 2], fromArray [3, 3, 3], NEA.singleton 1] + assert $ NEA.group (fromArray [ 1, 2, 2, 3, 3, 3, 1 ]) == fromArray + [ NEA.singleton 1 + , fromArray [ 2, 2 ] + , fromArray [ 3, 3, 3 ] + , NEA.singleton 1 + ] log "groupAll should group equal elements into arrays" - assert $ NEA.groupAll (fromArray [1, 2, 2, 3, 3, 3, 1]) == fromArray [fromArray [1, 1], fromArray [2, 2], fromArray [3, 3, 3]] - - log "groupBy should group consecutive equal elements into arrays based on an equivalence relation" - assert $ NEA.groupBy (\x y -> odd x && odd y) (fromArray [1, 1, 2, 2, 3, 3]) == fromArray [fromArray [1, 1], NEA.singleton 2, NEA.singleton 2, fromArray [3, 3]] + assert $ NEA.groupAll (fromArray [ 1, 2, 2, 3, 3, 3, 1 ]) == fromArray + [ fromArray [ 1, 1 ], fromArray [ 2, 2 ], fromArray [ 3, 3, 3 ] ] + + log + "groupBy should group consecutive equal elements into arrays based on an equivalence relation" + assert $ NEA.groupBy (\x y -> odd x && odd y) (fromArray [ 1, 1, 2, 2, 3, 3 ]) + == fromArray + [ fromArray [ 1, 1 ] + , NEA.singleton 2 + , NEA.singleton 2 + , fromArray [ 3, 3 ] + ] log "groupBy should be stable" - assert $ NEA.groupBy (\_ _ -> true) (fromArray [1, 2, 3]) == fromArray [fromArray [1, 2, 3]] + assert $ NEA.groupBy (\_ _ -> true) (fromArray [ 1, 2, 3 ]) == fromArray + [ fromArray [ 1, 2, 3 ] ] - log "groupAllBy should group equal elements into arrays based on the result of a comparison function" - assert $ NEA.groupAllBy (comparing Down) (fromArray [1, 3, 2, 4, 3, 3]) == fromArray [nea [4], nea [3, 3, 3], nea [2], nea [1]] + log + "groupAllBy should group equal elements into arrays based on the result of a comparison function" + assert $ NEA.groupAllBy (comparing Down) (fromArray [ 1, 3, 2, 4, 3, 3 ]) == + fromArray [ nea [ 4 ], nea [ 3, 3, 3 ], nea [ 2 ], nea [ 1 ] ] log "groupAllBy should be stable" - assert $ NEA.groupAllBy (\_ _ -> EQ) (fromArray [1, 2, 3]) == fromArray [nea [1, 2, 3]] + assert $ NEA.groupAllBy (\_ _ -> EQ) (fromArray [ 1, 2, 3 ]) == fromArray + [ nea [ 1, 2, 3 ] ] - log "nub should remove duplicate elements from the list, keeping the first occurence" - assert $ NEA.nub (fromArray [1, 2, 2, 3, 4, 1]) == fromArray [1, 2, 3, 4] + log + "nub should remove duplicate elements from the list, keeping the first occurence" + assert $ NEA.nub (fromArray [ 1, 2, 2, 3, 4, 1 ]) == fromArray [ 1, 2, 3, 4 ] - log "nubEq should remove duplicate elements from the list, keeping the first occurence" - assert $ NEA.nubEq (fromArray [1, 2, 2, 3, 4, 1]) == fromArray [1, 2, 3, 4] + log + "nubEq should remove duplicate elements from the list, keeping the first occurence" + assert $ NEA.nubEq (fromArray [ 1, 2, 2, 3, 4, 1 ]) == fromArray + [ 1, 2, 3, 4 ] - log "nubByEq should remove duplicate items from the list using a supplied predicate" + log + "nubByEq should remove duplicate items from the list using a supplied predicate" let nubPred = \x y -> if odd x then false else x == y - assert $ NEA.nubByEq nubPred (fromArray [1, 2, 2, 3, 3, 4, 4, 1]) == fromArray [1, 2, 3, 3, 4, 1] + assert $ NEA.nubByEq nubPred (fromArray [ 1, 2, 2, 3, 3, 4, 4, 1 ]) == + fromArray [ 1, 2, 3, 3, 4, 1 ] log "union should produce the union of two arrays" - assert $ NEA.union (fromArray [1, 2, 3]) (fromArray [2, 3, 4]) == fromArray [1, 2, 3, 4] - assert $ NEA.union (fromArray [1, 1, 2, 3]) (fromArray [2, 3, 4]) == fromArray [1, 1, 2, 3, 4] + assert $ NEA.union (fromArray [ 1, 2, 3 ]) (fromArray [ 2, 3, 4 ]) == + fromArray [ 1, 2, 3, 4 ] + assert $ NEA.union (fromArray [ 1, 1, 2, 3 ]) (fromArray [ 2, 3, 4 ]) == + fromArray [ 1, 1, 2, 3, 4 ] - log "unionBy should produce the union of two arrays using the specified equality relation" - assert $ NEA.unionBy (\_ y -> y < 5) (fromArray [1, 2, 3]) (fromArray [2, 3, 4, 5, 6]) == fromArray [1, 2, 3, 5, 6] + log + "unionBy should produce the union of two arrays using the specified equality relation" + assert $ + NEA.unionBy (\_ y -> y < 5) (fromArray [ 1, 2, 3 ]) + (fromArray [ 2, 3, 4, 5, 6 ]) == fromArray [ 1, 2, 3, 5, 6 ] log "delete should remove the first matching item from an array" - assert $ NEA.delete 1 (fromArray [1, 2, 1]) == [2, 1] - assert $ NEA.delete 2 (fromArray [1, 2, 1]) == [1, 1] + assert $ NEA.delete 1 (fromArray [ 1, 2, 1 ]) == [ 2, 1 ] + assert $ NEA.delete 2 (fromArray [ 1, 2, 1 ]) == [ 1, 1 ] - log "deleteBy should remove the first equality-relation-matching item from an array" - assert $ NEA.deleteBy (/=) 2 (fromArray [1, 2, 1]) == [2, 1] - assert $ NEA.deleteBy (/=) 1 (fromArray [1, 2, 1]) == [1, 1] + log + "deleteBy should remove the first equality-relation-matching item from an array" + assert $ NEA.deleteBy (/=) 2 (fromArray [ 1, 2, 1 ]) == [ 2, 1 ] + assert $ NEA.deleteBy (/=) 1 (fromArray [ 1, 2, 1 ]) == [ 1, 1 ] log "intersect should return the intersection of two arrays" - assert $ NEA.intersect (fromArray [1, 2, 3, 4, 3, 2, 1]) (fromArray [1, 1, 2, 3]) == [1, 2, 3, 3, 2, 1] + assert $ + NEA.intersect (fromArray [ 1, 2, 3, 4, 3, 2, 1 ]) (fromArray [ 1, 1, 2, 3 ]) + == [ 1, 2, 3, 3, 2, 1 ] - log "intersectBy should return the intersection of two arrays using the specified equivalence relation" - assert $ NEA.intersectBy (\x y -> (x * 2) == y) (fromArray [1, 2, 3]) (fromArray [2, 6]) == [1, 3] + log + "intersectBy should return the intersection of two arrays using the specified equivalence relation" + assert $ + NEA.intersectBy (\x y -> (x * 2) == y) (fromArray [ 1, 2, 3 ]) + (fromArray [ 2, 6 ]) == [ 1, 3 ] log "zipWith should use the specified function to zip two arrays together" - assert $ NEA.zipWith (\x y -> [show x, y]) (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) == fromArray [["1", "a"], ["2", "b"], ["3", "c"]] + assert $ + NEA.zipWith (\x y -> [ show x, y ]) (fromArray [ 1, 2, 3 ]) + (fromArray [ "a", "b", "c" ]) == fromArray + [ [ "1", "a" ], [ "2", "b" ], [ "3", "c" ] ] log "zipWithA should use the specified function to zip two lists together" - assert $ NEA.zipWithA (\x y -> Just $ Tuple x y) (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) == Just (fromArray [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) + assert $ + NEA.zipWithA (\x y -> Just $ Tuple x y) (fromArray [ 1, 2, 3 ]) + (fromArray [ "a", "b", "c" ]) == Just + (fromArray [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) log "zip should use the specified function to zip two lists together" - assert $ NEA.zip (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) == fromArray [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] + assert $ NEA.zip (fromArray [ 1, 2, 3 ]) (fromArray [ "a", "b", "c" ]) == + fromArray [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ] log "unzip should deconstruct a list of tuples into a tuple of lists" - assert $ NEA.unzip (fromArray [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) == Tuple (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) + assert $ NEA.unzip (fromArray [ Tuple 1 "a", Tuple 2 "b", Tuple 3 "c" ]) == + Tuple (fromArray [ 1, 2, 3 ]) (fromArray [ "a", "b", "c" ]) - log "any should return true if at least one array element satisfy the given predicate" - assert $ NEA.any (_ > 0) $ fromArray [-1, 0, 1] - assert $ not $ NEA.any (_ > 0) $ fromArray [-1, -2, -3] + log + "any should return true if at least one array element satisfy the given predicate" + assert $ NEA.any (_ > 0) $ fromArray [ -1, 0, 1 ] + assert $ not $ NEA.any (_ > 0) $ fromArray [ -1, -2, -3 ] - log "all should return true if all the array elements satisfy the given predicate" - assert $ NEA.all (_ > 0) $ fromArray [1, 2, 3] - assert $ not $ NEA.all (_ > 0) $ fromArray [-1, -2, -3] + log + "all should return true if all the array elements satisfy the given predicate" + assert $ NEA.all (_ > 0) $ fromArray [ 1, 2, 3 ] + assert $ not $ NEA.all (_ > 0) $ fromArray [ -1, -2, -3 ] log "fromFoldable" - for_ (fromArray [[], [1], [1,2], [1,2,3,4,5]]) \xs -> do + for_ (fromArray [ [], [ 1 ], [ 1, 2 ], [ 1, 2, 3, 4, 5 ] ]) \xs -> do assert $ NEA.fromFoldable xs == NEA.fromArray xs log "toUnfoldable" let toUnfoldableId xs = NEA.toUnfoldable xs == NEA.toArray xs traverse_ (assert <<< toUnfoldableId) $ - fromArray ( - [ fromArray [1] - , fromArray [1,2,3] - , fromArray [2,3,1] - , fromArray [4,0,0,1,25,36,458,5842,23757] - ]) + fromArray + ( [ fromArray [ 1 ] + , fromArray [ 1, 2, 3 ] + , fromArray [ 2, 3, 1 ] + , fromArray [ 4, 0, 0, 1, 25, 36, 458, 5842, 23757 ] + ] + ) log "toUnfoldable1" assert $ NEA.toUnfoldable1 (NEA.range 0 9) == 0 :| A.range 1 9 @@ -378,43 +496,76 @@ testNonEmptyArray = do assert $ U1.range 0 9 == NEA.range 0 9 log "foldMap1 should work" - assert $ foldMap1 Additive (fromArray [1, 2, 3, 4]) == Additive 10 + assert $ foldMap1 Additive (fromArray [ 1, 2, 3, 4 ]) == Additive 10 log "fold1 should work" -- test through sum - assert $ sum (fromArray [1, 2, 3, 4]) == 10 + assert $ sum (fromArray [ 1, 2, 3, 4 ]) == 10 log "foldr1 should work" - assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b", "c", "d"]) == "(a(b(cd)))" - assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b"]) == "(ab)" - assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a"]) == "a" + assert $ + foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a", "b", "c", "d" ]) == + "(a(b(cd)))" + assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a", "b" ]) == + "(ab)" + assert $ foldr1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a" ]) == "a" log "foldl1 should work" - assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b", "c", "d"]) == "(((ab)c)d)" - assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a", "b"]) == "(ab)" - assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray ["a"]) == "a" + assert $ + foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a", "b", "c", "d" ]) == + "(((ab)c)d)" + assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a", "b" ]) == + "(ab)" + assert $ foldl1 (\l r -> "(" <> l <> r <> ")") (fromArray [ "a" ]) == "a" log "traverse1 should work" - assert $ traverse1 Just (fromArray [1, 2, 3, 4]) == NEA.fromArray [1, 2, 3, 4] + assert $ traverse1 Just (fromArray [ 1, 2, 3, 4 ]) == NEA.fromArray + [ 1, 2, 3, 4 ] log "transpose swaps rows and columns for a regular two-dimension array" - assert $ NEA.transpose (fromArray [ (fromArray [1,2,3]), (fromArray [4,5,6]), (fromArray [7,8,9])]) == - (fromArray [ (fromArray [1,4,7]), (fromArray [2,5,8]), (fromArray [3,6,9])]) - + assert $ + NEA.transpose + ( fromArray + [ (fromArray [ 1, 2, 3 ]) + , (fromArray [ 4, 5, 6 ]) + , (fromArray [ 7, 8, 9 ]) + ] + ) == + ( fromArray + [ (fromArray [ 1, 4, 7 ]) + , (fromArray [ 2, 5, 8 ]) + , (fromArray [ 3, 6, 9 ]) + ] + ) + log "transpose skips elements when rows don't match" - assert $ NEA.transpose (fromArray [ (fromArray [10,11]), (fromArray [20]), (fromArray [30,31,32])]) == - (fromArray [ (fromArray [10,20,30]), (fromArray [11,31]), (fromArray [32])]) + assert $ + NEA.transpose + ( fromArray + [ (fromArray [ 10, 11 ]) + , (fromArray [ 20 ]) + , (fromArray [ 30, 31, 32 ]) + ] + ) == + ( fromArray + [ (fromArray [ 10, 20, 30 ]) + , (fromArray [ 11, 31 ]) + , (fromArray [ 32 ]) + ] + ) log "transpose' handles the singleton empty array" - assert $ NEA.transpose' (fromArray [ [] ]) == (Nothing :: Maybe (NEA.NonEmptyArray (Array Int))) + assert $ NEA.transpose' (fromArray [ [] ]) == + (Nothing :: Maybe (NEA.NonEmptyArray (Array Int))) log "transpose' swaps rows and columns for a regular two-dimension array" - assert $ NEA.transpose' (fromArray [[1,2,3], [4,5,6], [7,8,9]]) == - (Just $ fromArray [[1,4,7], [2,5,8], [3,6,9]]) - + assert $ NEA.transpose' (fromArray [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]) + == + (Just $ fromArray [ [ 1, 4, 7 ], [ 2, 5, 8 ], [ 3, 6, 9 ] ]) + log "transpose' skips elements when rows don't match" - assert $ NEA.transpose' (fromArray [[10,11], [20], [30,31,32]]) == - (Just $ fromArray [[10,20,30], [11,31], [32]]) + assert $ NEA.transpose' (fromArray [ [ 10, 11 ], [ 20 ], [ 30, 31, 32 ] ]) == + (Just $ fromArray [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ]) odd :: Int -> Boolean odd n = n `mod` 2 /= zero diff --git a/test/Test/Data/Array/Partial.purs b/test/Test/Data/Array/Partial.purs index 27eaf757..4e6ee7e7 100644 --- a/test/Test/Data/Array/Partial.purs +++ b/test/Test/Data/Array/Partial.purs @@ -12,15 +12,15 @@ testArrayPartial :: Effect Unit testArrayPartial = do log "head should return the first item in an array" - assert $ unsafePartial $ head [1, 2, 3] == 1 - assert $ unsafePartial $ head [1] == 1 + assert $ unsafePartial $ head [ 1, 2, 3 ] == 1 + assert $ unsafePartial $ head [ 1 ] == 1 log "tail should return all but the first item in an array" - assert $ unsafePartial $ tail [1, 2, 3] == [2, 3] + assert $ unsafePartial $ tail [ 1, 2, 3 ] == [ 2, 3 ] log "last should return the last item of an array" - assert $ unsafePartial $ last [1, 2, 3] == 3 - assert $ unsafePartial $ last [1] == 1 + assert $ unsafePartial $ last [ 1, 2, 3 ] == 3 + assert $ unsafePartial $ last [ 1 ] == 1 log "init should return all but the last item of an array" - assert $ unsafePartial $ init [1, 2, 3] == [1, 2] + assert $ unsafePartial $ init [ 1, 2, 3 ] == [ 1, 2 ] diff --git a/test/Test/Data/Array/ST.purs b/test/Test/Data/Array/ST.purs index 6e42fc2f..abfb63e3 100644 --- a/test/Test/Data/Array/ST.purs +++ b/test/Test/Data/Array/ST.purs @@ -19,17 +19,20 @@ testArrayST = do log "run should produce an immutable array by running a constructor operation" - assert $ STA.run (do - arr <- STA.new - void $ STA.push 1 arr - void $ STA.push 2 arr - pure arr) == [1, 2] + assert $ + STA.run + ( do + arr <- STA.new + void $ STA.push 1 arr + void $ STA.push 2 arr + pure arr + ) == [ 1, 2 ] log "withArray should run an operation on a copy of an array" - let original = [1, 2, 3] - assert $ ST.run (withArray (STA.push 42) original) == [1, 2, 3, 42] - assert $ original == [1, 2, 3] + let original = [ 1, 2, 3 ] + assert $ ST.run (withArray (STA.push 42) original) == [ 1, 2, 3, 42 ] + assert $ original == [ 1, 2, 3 ] log "empty should produce an empty array" @@ -37,275 +40,394 @@ testArrayST = do log "thaw should produce an STArray from a standard array" - assert $ STA.run (STA.thaw [1, 2, 3]) == [1, 2, 3] + assert $ STA.run (STA.thaw [ 1, 2, 3 ]) == [ 1, 2, 3 ] log "freeze should produce a standard array from an STArray" - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.freeze arr) == [1, 2, 3] + assert $ + ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.freeze arr + ) == [ 1, 2, 3 ] log "unsafeThaw should produce an STArray from a standard array" - assert $ STA.run (STA.unsafeThaw [1, 2, 3]) == [1, 2, 3] + assert $ STA.run (STA.unsafeThaw [ 1, 2, 3 ]) == [ 1, 2, 3 ] log "length should return the number of items in an STArray" - assert $ ST.run (do - arr <- STA.thaw nil - length <- STA.length arr - pure $ length == 0) - - assert $ ST.run (do - arr <- STA.thaw [1] - length <- STA.length arr - pure $ length == 1) - - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - length <- STA.length arr - pure $ length == 5) + assert $ ST.run + ( do + arr <- STA.thaw nil + length <- STA.length arr + pure $ length == 0 + ) + + assert $ ST.run + ( do + arr <- STA.thaw [ 1 ] + length <- STA.length arr + pure $ length == 1 + ) + + assert $ ST.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + length <- STA.length arr + pure $ length == 5 + ) log "pop should remove elements from an STArray" - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.pop arr - pure arr) == [1, 2] + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.pop arr + pure arr + ) == [ 1, 2 ] log "pop should return the last element of an STArray" - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.pop arr) == Just 3 + assert $ + ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.pop arr + ) == Just 3 log "pop should return Nothing when given an empty array" - assert $ isNothing $ ST.run (do - arr <- STA.new - STA.pop arr) + assert $ isNothing $ ST.run + ( do + arr <- STA.new + STA.pop arr + ) log "push should append a value to the end of the array" - assert $ STA.run (do - arr <- STA.new - void $ STA.push 1 arr - void $ STA.push 2 arr - pure arr) == [1, 2] - - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.push 4 arr - pure arr) == [1, 2, 3, 4] + assert $ + STA.run + ( do + arr <- STA.new + void $ STA.push 1 arr + void $ STA.push 2 arr + pure arr + ) == [ 1, 2 ] + + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.push 4 arr + pure arr + ) == [ 1, 2, 3, 4 ] log "push should return the new length of the array" - assert $ ST.run (do - arr <- STA.thaw [unit, unit, unit] - STA.push unit arr) == 4 + assert $ + ST.run + ( do + arr <- STA.thaw [ unit, unit, unit ] + STA.push unit arr + ) == 4 log "pushAll should append multiple values to the end of the array" - assert $ STA.run (do - arr <- STA.new - void $ STA.pushAll [1, 2] arr - pure arr) == [1, 2] - - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.pushAll [4, 5, 6] arr - pure arr) == [1, 2, 3, 4, 5, 6] + assert $ + STA.run + ( do + arr <- STA.new + void $ STA.pushAll [ 1, 2 ] arr + pure arr + ) == [ 1, 2 ] + + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.pushAll [ 4, 5, 6 ] arr + pure arr + ) == [ 1, 2, 3, 4, 5, 6 ] log "pushAll should return the new length of the array" - assert $ ST.run (do - arr <- STA.thaw [unit, unit, unit] - STA.pushAll [unit, unit] arr) == 5 + assert $ + ST.run + ( do + arr <- STA.thaw [ unit, unit, unit ] + STA.pushAll [ unit, unit ] arr + ) == 5 log "peek should return Nothing when peeking a value outside the array bounds" - assert $ isNothing $ ST.run (do - arr <- STA.new - STA.peek 0 arr) + assert $ isNothing $ ST.run + ( do + arr <- STA.new + STA.peek 0 arr + ) - assert $ isNothing $ ST.run (do - arr <- STA.thaw [1] - STA.peek 1 arr) + assert $ isNothing $ ST.run + ( do + arr <- STA.thaw [ 1 ] + STA.peek 1 arr + ) - assert $ isNothing $ ST.run (do - arr <- STA.new - STA.peek (-1) arr) + assert $ isNothing $ ST.run + ( do + arr <- STA.new + STA.peek (-1) arr + ) log "peek should return the value at the specified index" - assert $ ST.run (do - arr <- STA.thaw [1] - STA.peek 0 arr) == Just 1 + assert $ + ST.run + ( do + arr <- STA.thaw [ 1 ] + STA.peek 0 arr + ) == Just 1 - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.peek 2 arr) == Just 3 + assert $ + ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.peek 2 arr + ) == Just 3 log "poke should return true when a value has been updated succesfully" - assert $ ST.run (do - arr <- STA.thaw [1] - STA.poke 0 10 arr) - - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.poke 2 30 arr) - - log "poke should return false when attempting to modify a value outside the array bounds" - - assert $ not $ ST.run (do - arr <- STA.new - STA.poke 0 10 arr) - - assert $ not $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.poke 3 100 arr) - - assert $ not $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.poke (-1) 100 arr) + assert $ ST.run + ( do + arr <- STA.thaw [ 1 ] + STA.poke 0 10 arr + ) + + assert $ ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.poke 2 30 arr + ) + + log + "poke should return false when attempting to modify a value outside the array bounds" + + assert $ not $ ST.run + ( do + arr <- STA.new + STA.poke 0 10 arr + ) + + assert $ not $ ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.poke 3 100 arr + ) + + assert $ not $ ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.poke (-1) 100 arr + ) log "poke should replace the value at the specified index" - assert $ STA.run (do - arr <- STA.thaw [1] - void $ STA.poke 0 10 arr - pure arr) == [10] - - log "poke should do nothing when attempting to modify a value outside the array bounds" - - assert $ STA.run (do - arr <- STA.thaw [1] - void $ STA.poke 1 2 arr - pure arr) == [1] + assert $ + STA.run + ( do + arr <- STA.thaw [ 1 ] + void $ STA.poke 0 10 arr + pure arr + ) == [ 10 ] + + log + "poke should do nothing when attempting to modify a value outside the array bounds" + + assert $ + STA.run + ( do + arr <- STA.thaw [ 1 ] + void $ STA.poke 1 2 arr + pure arr + ) == [ 1 ] log "shift should remove elements from an STArray" - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.shift arr - pure arr) == [2, 3] + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.shift arr + pure arr + ) == [ 2, 3 ] log "shift should return the first element of an STArray" - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3] - STA.shift arr) == Just 1 + assert $ + ST.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + STA.shift arr + ) == Just 1 log "shift should return Nothing when given an empty array" - assert $ isNothing $ ST.run (do - arr <- STA.new - STA.shift arr) + assert $ isNothing $ ST.run + ( do + arr <- STA.new + STA.shift arr + ) log "unshift should append a value to the front of the array" - assert $ STA.run (do - arr <- STA.new - void $ STA.unshift 1 arr - void $ STA.unshift 2 arr - pure arr) == [2, 1] - - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.unshift 4 arr - pure arr) == [4, 1, 2, 3] + assert $ + STA.run + ( do + arr <- STA.new + void $ STA.unshift 1 arr + void $ STA.unshift 2 arr + pure arr + ) == [ 2, 1 ] + + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.unshift 4 arr + pure arr + ) == [ 4, 1, 2, 3 ] log "unshift should return the new length of the array" - assert $ ST.run (do - arr <- STA.thaw [unit, unit, unit] - STA.unshift unit arr) == 4 + assert $ + ST.run + ( do + arr <- STA.thaw [ unit, unit, unit ] + STA.unshift unit arr + ) == 4 log "unshiftAll should append multiple values to the front of the array" - assert $ STA.run (do - arr <- STA.new - void $ STA.unshiftAll [1, 2] arr - pure arr) == [1, 2] - - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3] - void $ STA.unshiftAll [4, 5, 6] arr - pure arr) == [4, 5, 6, 1, 2, 3] + assert $ + STA.run + ( do + arr <- STA.new + void $ STA.unshiftAll [ 1, 2 ] arr + pure arr + ) == [ 1, 2 ] + + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3 ] + void $ STA.unshiftAll [ 4, 5, 6 ] arr + pure arr + ) == [ 4, 5, 6, 1, 2, 3 ] log "unshiftAll should return the new length of the array" - assert $ ST.run (do - arr <- STA.thaw [unit, unit, unit] - STA.unshiftAll [unit, unit] arr) == 5 - - log "sort should reorder a list into ascending order based on the result of compare" - assert $ STA.run ( - STA.sort =<< STA.unsafeThaw [1, 3, 2, 5, 6, 4] - ) == [1, 2, 3, 4, 5, 6] - assert $ STA.run ( - STA.sort =<< STA.unsafeThaw [defined 1, undefined, defined 2] - ) == [undefined, defined 1, defined 2] - - log "sortBy should reorder a list into ascending order based on the result of a comparison function" - assert $ STA.run ( - STA.sortBy (flip compare) =<< STA.unsafeThaw [1, 3, 2, 5, 6, 4] - ) == [6, 5, 4, 3, 2, 1] - - log "sortBy should not reorder elements that are equal according to a comparison function" + assert $ + ST.run + ( do + arr <- STA.thaw [ unit, unit, unit ] + STA.unshiftAll [ unit, unit ] arr + ) == 5 + + log + "sort should reorder a list into ascending order based on the result of compare" + assert $ + STA.run + ( STA.sort =<< STA.unsafeThaw [ 1, 3, 2, 5, 6, 4 ] + ) == [ 1, 2, 3, 4, 5, 6 ] + assert $ + STA.run + ( STA.sort =<< STA.unsafeThaw [ defined 1, undefined, defined 2 ] + ) == [ undefined, defined 1, defined 2 ] + + log + "sortBy should reorder a list into ascending order based on the result of a comparison function" + assert $ + STA.run + ( STA.sortBy (flip compare) =<< STA.unsafeThaw [ 1, 3, 2, 5, 6, 4 ] + ) == [ 6, 5, 4, 3, 2, 1 ] + + log + "sortBy should not reorder elements that are equal according to a comparison function" let s1 = map (Tuple "a") (range 1 100) - assert $ STA.run ( - STA.sortBy (comparing fst) =<< STA.unsafeThaw s1 - ) == s1 - - log "sortWith should reorder a list into ascending order based on the result of compare over a projection" - assert $ STA.run ( - STA.sortWith identity =<< STA.unsafeThaw [1, 3, 2, 5, 6, 4] - ) == [1, 2, 3, 4, 5, 6] - - log "sortWith should not reorder elements that are equal according to a projection" + assert $ + STA.run + ( STA.sortBy (comparing fst) =<< STA.unsafeThaw s1 + ) == s1 + + log + "sortWith should reorder a list into ascending order based on the result of compare over a projection" + assert $ + STA.run + ( STA.sortWith identity =<< STA.unsafeThaw [ 1, 3, 2, 5, 6, 4 ] + ) == [ 1, 2, 3, 4, 5, 6 ] + + log + "sortWith should not reorder elements that are equal according to a projection" let s2 = map (Tuple "a") (range 1 100) - assert $ STA.run ( - STA.sortWith fst =<< STA.unsafeThaw s2 - ) == s2 + assert $ + STA.run + ( STA.sortWith fst =<< STA.unsafeThaw s2 + ) == s2 log "splice should be able to delete multiple items at a specified index" - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - void $ STA.splice 1 3 [] arr - pure arr) == [1, 5] + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + void $ STA.splice 1 3 [] arr + pure arr + ) == [ 1, 5 ] log "splice should return the items removed" - assert $ ST.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - STA.splice 1 3 [] arr) == [2, 3, 4] + assert $ + ST.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + STA.splice 1 3 [] arr + ) == [ 2, 3, 4 ] log "splice should be able to insert multiple items at a specified index" - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - void $ STA.splice 1 0 [0, 100] arr - pure arr) == [1, 0, 100, 2, 3, 4, 5] + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + void $ STA.splice 1 0 [ 0, 100 ] arr + pure arr + ) == [ 1, 0, 100, 2, 3, 4, 5 ] log "splice should be able to delete and insert at the same time" - assert $ STA.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - void $ STA.splice 1 2 [0, 100] arr - pure arr) == [1, 0, 100, 4, 5] - - log "toAssocArray should return all items in the array with the correct indices and values" - - assert $ all (\{ value: v, index: i } -> v == i + 1) $ ST.run (do - arr <- STA.thaw [1, 2, 3, 4, 5] - STA.toAssocArray arr) - - assert $ all (\{ value: v, index: i } -> v == (i + 1) * 10) $ ST.run (do - arr <- STA.thaw [10, 20, 30, 40, 50] - STA.toAssocArray arr) + assert $ + STA.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + void $ STA.splice 1 2 [ 0, 100 ] arr + pure arr + ) == [ 1, 0, 100, 4, 5 ] + + log + "toAssocArray should return all items in the array with the correct indices and values" + + assert $ all (\{ value: v, index: i } -> v == i + 1) $ ST.run + ( do + arr <- STA.thaw [ 1, 2, 3, 4, 5 ] + STA.toAssocArray arr + ) + + assert $ all (\{ value: v, index: i } -> v == (i + 1) * 10) $ ST.run + ( do + arr <- STA.thaw [ 10, 20, 30, 40, 50 ] + STA.toAssocArray arr + ) nil :: Array Int nil = [] diff --git a/test/Test/Data/Array/ST/Partial.purs b/test/Test/Data/Array/ST/Partial.purs index 89c6f9eb..006e4db4 100644 --- a/test/Test/Data/Array/ST/Partial.purs +++ b/test/Test/Data/Array/ST/Partial.purs @@ -15,11 +15,11 @@ testArraySTPartial = do log "peekSTArray should return the value at the specified index" assert $ 2 == ST.run do - a <- thaw [1, 2, 3] + a <- thaw [ 1, 2, 3 ] unsafePartial $ STAP.peek 1 a log "pokeSTArray should modify the value at the specified index" - assert $ [1, 4, 3] == ST.run do - a <- thaw [1, 2, 3] + assert $ [ 1, 4, 3 ] == ST.run do + a <- thaw [ 1, 2, 3 ] unsafePartial $ STAP.poke 1 4 a unsafeFreeze a diff --git a/test/Test/Data/UndefinedOr.purs b/test/Test/Data/UndefinedOr.purs index 18c2e3b7..bf8d869d 100644 --- a/test/Test/Data/UndefinedOr.purs +++ b/test/Test/Data/UndefinedOr.purs @@ -7,8 +7,18 @@ foreign import data UndefinedOr :: Type -> Type foreign import undefined :: forall a. UndefinedOr a foreign import defined :: forall a. a -> UndefinedOr a -foreign import eqUndefinedOrImpl :: forall a. (a -> a -> Boolean) -> UndefinedOr a -> UndefinedOr a -> Boolean -foreign import compareUndefinedOrImpl :: forall a. Ordering -> Ordering -> Ordering -> (a -> a -> Ordering) -> UndefinedOr a -> UndefinedOr a -> Ordering +foreign import eqUndefinedOrImpl + :: forall a. (a -> a -> Boolean) -> UndefinedOr a -> UndefinedOr a -> Boolean + +foreign import compareUndefinedOrImpl + :: forall a + . Ordering + -> Ordering + -> Ordering + -> (a -> a -> Ordering) + -> UndefinedOr a + -> UndefinedOr a + -> Ordering instance eqUndefinedOr :: Eq a => Eq (UndefinedOr a) where eq = eqUndefinedOrImpl eq diff --git a/test/regression/array_st.lua b/test/regression/array_st.lua index 33d3a05d..196298d4 100644 --- a/test/regression/array_st.lua +++ b/test/regression/array_st.lua @@ -6,7 +6,6 @@ -- especially the two overlap directions of `move` that a naive copy gets wrong. -- -- Run from the repo root: `lua test/regression/array_st.lua`. - local ST = dofile("src/Data/Array/ST.lua") local A = dofile("src/Data/Array.lua") @@ -14,9 +13,7 @@ local failures = 0 local function eqArray(a, b) if #a ~= #b then return false end - for i = 1, #a do - if a[i] ~= b[i] then return false end - end + for i = 1, #a do if a[i] ~= b[i] then return false end end return true end @@ -49,108 +46,118 @@ end -- freeze (= copyImpl, the move-to-fresh-table path) is an independent copy. do - local xs = { 1, 2, 3 } + local xs = {1, 2, 3} local copy = ST.freeze(xs)() - checkArray("freeze copies", copy, { 1, 2, 3 }) + checkArray("freeze copies", copy, {1, 2, 3}) copy[1] = 99 check("freeze is independent", xs[1] == 1, "source mutated to " .. tostring(xs[1])) end -- pushAllImpl appends and reports the new length. do - local xs = { 1, 2 } - local n = ST.pushAllImpl({ 3, 4, 5 }, xs) - checkArray("pushAllImpl appends", xs, { 1, 2, 3, 4, 5 }) + local xs = {1, 2} + local n = ST.pushAllImpl({3, 4, 5}, xs) + checkArray("pushAllImpl appends", xs, {1, 2, 3, 4, 5}) check("pushAllImpl returns length", n == 5, "got " .. tostring(n)) end -- spliceImpl shifting the tail LEFT (destination before source: forward copy). do - local xs = { 10, 20, 30, 40, 50 } + local xs = {10, 20, 30, 40, 50} ST.spliceImpl(1, 1, {}, xs) -- move(xs, 3, 5, 2, xs) - checkArray("spliceImpl shift-left overlap", xs, { 10, 30, 40, 50, 50 }) + checkArray("spliceImpl shift-left overlap", xs, {10, 30, 40, 50, 50}) end -- spliceImpl shifting the tail RIGHT (destination inside source: must copy -- backwards or it clobbers). This is the case a naive forward loop breaks. do - local xs = { 1, 2, 3, 4 } - ST.spliceImpl(0, 0, { 9 }, xs) -- move(xs, 1, 4, 2, xs) - checkArray("spliceImpl shift-right overlap", xs, { 1, 1, 2, 3, 4 }) + local xs = {1, 2, 3, 4} + ST.spliceImpl(0, 0, {9}, xs) -- move(xs, 1, 4, 2, xs) + checkArray("spliceImpl shift-right overlap", xs, {1, 1, 2, 3, 4}) end -- sortByImpl sorts in place (it copies through move internally). do - local function compare(x) return function(y) - if x < y then return -1 elseif x > y then return 1 else return 0 end - end end + local function compare(x) + return function(y) + if x < y then + return -1 + elseif x > y then + return 1 + else + return 0 + end + end + end local function fromOrdering(o) return o end - local xs = { 3, 1, 2, 1 } + local xs = {3, 1, 2, 1} local sorted = ST.sortByImpl(compare, fromOrdering, xs) - checkArray("sortByImpl sorts ascending", sorted, { 1, 1, 2, 3 }) + checkArray("sortByImpl sorts ascending", sorted, {1, 1, 2, 3}) end -- sortByImpl is stable: records with equal keys keep their input order. do - local function byKey(x) return function(y) - if x.k < y.k then return -1 elseif x.k > y.k then return 1 else return 0 end - end end + local function byKey(x) + return function(y) + if x.k < y.k then + return -1 + elseif x.k > y.k then + return 1 + else + return 0 + end + end + end local function fromOrdering(o) return o end -- Two elements share key 1 ("a" before "b"); a stable sort keeps a before b. - local xs = { - { k = 1, id = "a" }, - { k = 0, id = "c" }, - { k = 1, id = "b" }, - } + local xs = {{k = 1, id = "a"}, {k = 0, id = "c"}, {k = 1, id = "b"}} ST.sortByImpl(byKey, fromOrdering, xs) local keys, ids = {}, {} for i = 1, #xs do keys[i], ids[i] = xs[i].k, xs[i].id end - checkArray("sortByImpl orders by key", keys, { 0, 1, 1 }) + checkArray("sortByImpl orders by key", keys, {0, 1, 1}) check("sortByImpl is stable on equal keys", ids[1] == "c" and ids[2] == "a" and ids[3] == "b", - "got order " .. table.concat(ids, ",")) + "got order " .. table.concat(ids, ",")) end -------------------------------------------------------------------------------- -- Data/Array.lua: unpack-based operations ------------------------------------ -local function just(x) return { tag = "just", value = x } end -local nothing = { tag = "nothing" } +local function just(x) return {tag = "just", value = x} end +local nothing = {tag = "nothing"} -- unconsImpl splits head / tail; the tail is `{ unpack(xs, 2) }`. do - local function empty(_) return { tag = "empty" } end - local function next(h) return function(t) return { tag = "cons", head = h, tail = t } end end - local r = A.unconsImpl(empty, next, { 1, 2, 3 }) + local function empty(_) return {tag = "empty"} end + local function next(h) return function(t) return {tag = "cons", head = h, tail = t} end end + local r = A.unconsImpl(empty, next, {1, 2, 3}) check("unconsImpl head", r.head == 1, "got " .. tostring(r.head)) - checkArray("unconsImpl tail", r.tail, { 2, 3 }) + checkArray("unconsImpl tail", r.tail, {2, 3}) check("unconsImpl empty", A.unconsImpl(empty, next, {}).tag == "empty", "non-empty result") end -- _insertAt copies via unpack, then inserts; the source is left untouched. do - local src = { 1, 2, 3 } + local src = {1, 2, 3} local r = A._insertAt(just, nothing, 1, 99, src) - checkArray("_insertAt result", r.value, { 1, 99, 2, 3 }) - checkArray("_insertAt keeps source", src, { 1, 2, 3 }) + checkArray("_insertAt result", r.value, {1, 99, 2, 3}) + checkArray("_insertAt keeps source", src, {1, 2, 3}) check("_insertAt out of range", A._insertAt(just, nothing, 9, 0, src).tag == "nothing", "expected nothing") end -- _deleteAt copies via unpack, then removes. do - local r = A._deleteAt(just, nothing, 1, { 1, 2, 3 }) - checkArray("_deleteAt result", r.value, { 1, 3 }) + local r = A._deleteAt(just, nothing, 1, {1, 2, 3}) + checkArray("_deleteAt result", r.value, {1, 3}) end -- _updateAt copies via unpack, then updates one slot. do local function times100(x) return x * 100 end - local r = A._updateAt(just, nothing, 1, times100, { 1, 2, 3 }) - checkArray("_updateAt result", r.value, { 1, 200, 3 }) + local r = A._updateAt(just, nothing, 1, times100, {1, 2, 3}) + checkArray("_updateAt result", r.value, {1, 200, 3}) end -------------------------------------------------------------------------------- -if failures > 0 then - error(failures .. " regression check(s) failed") -end +if failures > 0 then error(failures .. " regression check(s) failed") end print("purescript-lua-arrays: all FFI regression checks passed") diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 00000000..0f575736 --- /dev/null +++ b/treefmt.nix @@ -0,0 +1,43 @@ +{ pkgs, ... }: +{ + projectRootFile = "flake.nix"; + + # Nix — RFC 166 formatter. + programs.nixfmt.enable = true; + + # Dhall — spago.dhall / packages.dhall layout. + programs.dhall.enable = true; + + # PureScript — purs-tidy is not a first-class treefmt program, so wire it via + # the generic mechanism. It picks up `.tidyrc.json` from the project root. + settings.formatter.purs-tidy = { + command = "${pkgs.purs-tidy}/bin/purs-tidy"; + options = [ "format-in-place" ]; + includes = [ "*.purs" ]; + }; + + # Lua FFI — LuaFormatter keeps the parentheses pslua's foreign-file parser + # requires (unlike StyLua, which strips them). Config in `.lua-format`. + settings.formatter.lua-format = { + command = "${pkgs.luaformatter}/bin/lua-format"; + options = [ + "-i" + "-c" + ".lua-format" + ]; + includes = [ "*.lua" ]; + }; + + # Never format generated output or vendored trees. + settings.global.excludes = [ + "dist/*" + "output/*" + ".spago/*" + "node_modules/*" + "*.lock" + "flake.lock" + "spago.lock" + ".tidyrc.json" + ".lua-format" + ]; +}