diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d624d2e..4dc2d20 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 db67e9a..e070528 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 0000000..2945014 --- /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 0000000..8636af8 --- /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 dde531a..a312901 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 (only if the fork has `scripts/test`): `nix develop -c bash ./scripts/test` -- 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/flake.lock b/flake.lock index 6b6c417..c47b792 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 8138f67..4d86c4b 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,9 +48,28 @@ 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 = { extra-substituters = [ "https://cache.iog.io" diff --git a/src/Data/Bifoldable.purs b/src/Data/Bifoldable.purs index 9b18723..b09babf 100644 --- a/src/Data/Bifoldable.purs +++ b/src/Data/Bifoldable.purs @@ -54,7 +54,11 @@ instance bifoldableFlip :: Bifoldable p => Bifoldable (Flip p) where bifoldl r l u (Flip p) = bifoldl l r u p bifoldMap r l (Flip p) = bifoldMap l r p -instance bifoldableProduct2 :: (Bifoldable f, Bifoldable g) => Bifoldable (Product2 f g) where +instance bifoldableProduct2 :: + ( Bifoldable f + , Bifoldable g + ) => + Bifoldable (Product2 f g) where bifoldr l r u m = bifoldrDefault l r u m bifoldl l r u m = bifoldlDefault l r u m bifoldMap l r (Product2 f g) = bifoldMap l r f <> bifoldMap l r g @@ -105,8 +109,9 @@ bifoldlDefault -> c bifoldlDefault f g z p = unwrap - (unwrap - (bifoldMap (Dual <<< Endo <<< flip f) (Dual <<< Endo <<< flip g) p)) + ( unwrap + (bifoldMap (Dual <<< Endo <<< flip f) (Dual <<< Endo <<< flip g) p) + ) z -- | A default implementation of `bifoldMap` using `bifoldr`. @@ -137,7 +142,6 @@ bifoldMapDefaultL -> m bifoldMapDefaultL f g = bifoldl (\m a -> m <> f a) (\m b -> m <> g b) mempty - -- | Fold a data structure, accumulating values in a monoidal type. bifold :: forall t m. Bifoldable t => Monoid m => t m m -> m bifold = bifoldMap identity identity diff --git a/src/Data/Bitraversable.purs b/src/Data/Bitraversable.purs index 6760549..664d900 100644 --- a/src/Data/Bitraversable.purs +++ b/src/Data/Bitraversable.purs @@ -1,5 +1,7 @@ module Data.Bitraversable - ( class Bitraversable, bitraverse, bisequence + ( class Bitraversable + , bitraverse + , bisequence , bitraverseDefault , bisequenceDefault , ltraverse @@ -35,7 +37,13 @@ import Data.Tuple (Tuple(..)) -- | - `bitraverseDefault` -- | - `bisequenceDefault` class (Bifunctor t, Bifoldable t) <= Bitraversable t where - bitraverse :: forall f a b c d. Applicative f => (a -> f c) -> (b -> f d) -> t a b -> f (t c d) + bitraverse + :: forall f a b c d + . Applicative f + => (a -> f c) + -> (b -> f d) + -> t a b + -> f (t c d) bisequence :: forall f a b. Applicative f => t (f a) (f b) -> f (t a b) instance bitraversableClown :: Traversable f => Bitraversable (Clown f) where @@ -50,8 +58,14 @@ instance bitraversableFlip :: Bitraversable p => Bitraversable (Flip p) where bitraverse r l (Flip p) = Flip <$> bitraverse l r p bisequence (Flip p) = Flip <$> bisequence p -instance bitraversableProduct2 :: (Bitraversable f, Bitraversable g) => Bitraversable (Product2 f g) where - bitraverse l r (Product2 f g) = Product2 <$> bitraverse l r f <*> bitraverse l r g +instance bitraversableProduct2 :: + ( Bitraversable f + , Bitraversable g + ) => + Bitraversable (Product2 f g) where + bitraverse l r (Product2 f g) = Product2 <$> bitraverse l r f <*> bitraverse l + r + g bisequence (Product2 f g) = Product2 <$> bisequence f <*> bisequence g instance bitraversableEither :: Bitraversable Either where diff --git a/src/Data/Foldable.purs b/src/Data/Foldable.purs index b98cc1e..c2e44d2 100644 --- a/src/Data/Foldable.purs +++ b/src/Data/Foldable.purs @@ -1,6 +1,12 @@ module Data.Foldable - ( class Foldable, foldr, foldl, foldMap - , foldrDefault, foldlDefault, foldMapDefaultL, foldMapDefaultR + ( class Foldable + , foldr + , foldl + , foldMap + , foldrDefault + , foldlDefault + , foldMapDefaultL + , foldMapDefaultR , fold , foldM , traverse_ @@ -75,17 +81,19 @@ class Foldable f where foldl :: forall a b. (b -> a -> b) -> b -> f a -> b foldMap :: forall a m. Monoid m => (a -> m) -> f a -> m - -- | This internal type is used just to implement a stack-safe and performant foldrDefault and foldlDefault. -- | It has O(1) append (because foldrDefault and foldlDefault are implemented in terms of foldMap), and -- | an amortized O(1) uncons/unsnoc. It behaves similarly to a CatList -data FreeMonoidTree a = Empty | Node a | Append (FreeMonoidTree a) (FreeMonoidTree a) +data FreeMonoidTree a + = Empty + | Node a + | Append (FreeMonoidTree a) (FreeMonoidTree a) -instance Foldable FreeMonoidTree where +instance Foldable FreeMonoidTree where -- these folding implementations could be written more plainly, but are optimized to minimize conditionals. foldl fn = (\a b -> go a b Empty) where - go acc lhs rhs = + go acc lhs rhs = case lhs of Node a -> go (fn acc a) rhs Empty Append xs ys -> @@ -101,27 +109,29 @@ instance Foldable FreeMonoidTree where _ -> go acc rhs Empty foldr fn = (\a b -> go a Empty b) - where - go acc lhs rhs = - case rhs of + where + go acc lhs rhs = + case rhs of Node a -> go (fn a acc) Empty lhs - Append xs ys -> - case xs of + Append xs ys -> + case xs of Empty -> go acc lhs ys - _ -> - case lhs of + _ -> + case lhs of Empty -> go acc xs ys _ -> go acc (Append lhs xs) ys - Empty -> - case lhs of + Empty -> + case lhs of Empty -> acc _ -> go acc Empty lhs - foldMap = foldMapDefaultR -instance Semigroup (FreeMonoidTree a) where append = Append -instance Monoid (FreeMonoidTree a) where mempty = Empty +instance Semigroup (FreeMonoidTree a) where + append = Append + +instance Monoid (FreeMonoidTree a) where + mempty = Empty -- | A default implementation of `foldr` using `foldMap`. -- | @@ -184,11 +194,11 @@ foreign import foldrArray :: forall a b. (a -> b -> b) -> b -> Array a -> b foreign import foldlArray :: forall a b. (b -> a -> b) -> b -> Array a -> b instance foldableMaybe :: Foldable Maybe where - foldr _ z Nothing = z + foldr _ z Nothing = z foldr f z (Just x) = x `f` z - foldl _ z Nothing = z + foldl _ z Nothing = z foldl f z (Just x) = z `f` x - foldMap _ Nothing = mempty + foldMap _ Nothing = mempty foldMap f (Just x) = f x instance foldableFirst :: Foldable First where @@ -227,11 +237,11 @@ instance foldableMultiplicative :: Foldable Multiplicative where foldMap f (Multiplicative x) = f x instance foldableEither :: Foldable (Either a) where - foldr _ z (Left _) = z + foldr _ z (Left _) = z foldr f z (Right x) = f x z - foldl _ z (Left _) = z + foldl _ z (Left _) = z foldl f z (Right x) = f z x - foldMap _ (Left _) = mempty + foldMap _ (Left _) = mempty foldMap f (Right x) = f x instance foldableTuple :: Foldable (Tuple a) where @@ -254,7 +264,11 @@ instance foldableProduct :: (Foldable f, Foldable g) => Foldable (Product f g) w foldl f z (Product (Tuple fa ga)) = foldl f (foldl f z fa) ga foldMap f (Product (Tuple fa ga)) = foldMap f fa <> foldMap f ga -instance foldableCoproduct :: (Foldable f, Foldable g) => Foldable (Coproduct f g) where +instance foldableCoproduct :: + ( Foldable f + , Foldable g + ) => + Foldable (Coproduct f g) where foldr f z = coproduct (foldr f z) (foldr f z) foldl f z = coproduct (foldl f z) (foldl f z) foldMap f = coproduct (foldMap f) (foldMap f) @@ -277,7 +291,8 @@ fold = foldMap identity -- | -- | Note: this function is not generally stack-safe, e.g., for monads which -- | build up thunks a la `Eff`. -foldM :: forall f m a b. Foldable f => Monad m => (b -> a -> m b) -> b -> f a -> m b +foldM + :: forall f m a b. Foldable f => Monad m => (b -> a -> m b) -> b -> f a -> m b foldM f b0 = foldl (\b a -> b >>= flip f a) (pure b0) -- | Traverse a data structure, performing some effects encoded by an @@ -357,7 +372,7 @@ intercalate :: forall f m. Foldable f => Monoid m => m -> f m -> m intercalate sep xs = (foldl go { init: true, acc: mempty } xs).acc where go { init: true } x = { init: false, acc: x } - go { acc: acc } x = { init: false, acc: acc <> sep <> x } + go { acc: acc } x = { init: false, acc: acc <> sep <> x } -- | `foldMap` but with each element surrounded by some fixed value. -- | @@ -376,9 +391,11 @@ intercalate sep xs = (foldl go { init: true, acc: mempty } xs).acc -- | > surroundMap "*" show [1, 2, 3] -- | = "*1*2*3*" -- | ``` -surroundMap :: forall f a m. Foldable f => Semigroup m => m -> (a -> m) -> f a -> m +surroundMap + :: forall f a m. Foldable f => Semigroup m => m -> (a -> m) -> f a -> m surroundMap d t f = unwrap (foldMap joined f) d - where joined a = Endo \m -> d <> t a <> m + where + joined a = Endo \m -> d <> t a <> m -- | `fold` but with each element surrounded by some fixed value. -- | @@ -415,7 +432,7 @@ or = any identity -- | `all f` is the same as `and <<< map f`; map a function over the structure, -- | and then get the conjunction of the results. all :: forall a b f. Foldable f => HeytingAlgebra b => (a -> b) -> f a -> b -all = alaF Conj foldMap +all = alaF Conj foldMap -- | `any f` is the same as `or <<< map f`; map a function over the structure, -- | and then get the disjunction of the results. @@ -446,9 +463,8 @@ indexl idx = _.elem <<< foldl go { elem: Nothing, pos: 0 } case cursor.elem of Just _ -> cursor _ -> - if cursor.pos == idx - then { elem: Just a, pos: cursor.pos } - else { pos: cursor.pos + 1, elem: cursor.elem } + if cursor.pos == idx then { elem: Just a, pos: cursor.pos } + else { pos: cursor.pos + 1, elem: cursor.elem } -- | Try to get nth element from the right in a data structure indexr :: forall a f. Foldable f => Int -> f a -> Maybe a @@ -458,9 +474,8 @@ indexr idx = _.elem <<< foldr go { elem: Nothing, pos: 0 } case cursor.elem of Just _ -> cursor _ -> - if cursor.pos == idx - then { elem: Just a, pos: cursor.pos } - else { pos: cursor.pos + 1, elem: cursor.elem } + if cursor.pos == idx then { elem: Just a, pos: cursor.pos } + else { pos: cursor.pos + 1, elem: cursor.elem } -- | Try to find an element in a data structure which satisfies a predicate. find :: forall a f. Foldable f => (a -> Boolean) -> f a -> Maybe a @@ -486,7 +501,7 @@ maximum = maximumBy compare maximumBy :: forall a f. Foldable f => (a -> a -> Ordering) -> f a -> Maybe a maximumBy cmp = foldl max' Nothing where - max' Nothing x = Just x + max' Nothing x = Just x max' (Just x) y = Just (if cmp x y == GT then x else y) -- | Find the smallest element of a structure, according to its `Ord` instance. @@ -499,7 +514,7 @@ minimum = minimumBy compare minimumBy :: forall a f. Foldable f => (a -> a -> Ordering) -> f a -> Maybe a minimumBy cmp = foldl min' Nothing where - min' Nothing x = Just x + min' Nothing x = Just x min' (Just x) y = Just (if cmp x y == LT then x else y) -- | Test whether the structure is empty. @@ -516,4 +531,5 @@ length = foldl (\c _ -> add one c) zero -- | Lookup a value in a data structure of `Tuple`s, generalizing association lists. lookup :: forall a b f. Foldable f => Eq a => a -> f (Tuple a b) -> Maybe b -lookup a = unwrap <<< foldMap \(Tuple a' b) -> First (if a == a' then Just b else Nothing) +lookup a = unwrap <<< foldMap \(Tuple a' b) -> First + (if a == a' then Just b else Nothing) diff --git a/src/Data/FoldableWithIndex.purs b/src/Data/FoldableWithIndex.purs index 258fe1e..97242cf 100644 --- a/src/Data/FoldableWithIndex.purs +++ b/src/Data/FoldableWithIndex.purs @@ -1,5 +1,8 @@ module Data.FoldableWithIndex - ( class FoldableWithIndex, foldrWithIndex, foldlWithIndex, foldMapWithIndex + ( class FoldableWithIndex + , foldrWithIndex + , foldlWithIndex + , foldMapWithIndex , foldrWithIndexDefault , foldlWithIndexDefault , foldMapWithIndexDefaultR @@ -75,7 +78,8 @@ foldrWithIndexDefault -> b -> f a -> b -foldrWithIndexDefault c u xs = unwrap (foldMapWithIndex (\i -> Endo <<< c i) xs) u +foldrWithIndexDefault c u xs = unwrap (foldMapWithIndex (\i -> Endo <<< c i) xs) + u -- | A default implementation of `foldlWithIndex` using `foldMapWithIndex`. -- | @@ -88,7 +92,9 @@ foldlWithIndexDefault -> b -> f a -> b -foldlWithIndexDefault c u xs = unwrap (unwrap (foldMapWithIndex (\i -> Dual <<< Endo <<< flip (c i)) xs)) u +foldlWithIndexDefault c u xs = unwrap + (unwrap (foldMapWithIndex (\i -> Dual <<< Endo <<< flip (c i)) xs)) + u -- | A default implementation of `foldMapWithIndex` using `foldrWithIndex`. -- | @@ -117,8 +123,10 @@ foldMapWithIndexDefaultL foldMapWithIndexDefaultL f = foldlWithIndex (\i acc x -> acc <> f i x) mempty instance foldableWithIndexArray :: FoldableWithIndex Int Array where - foldrWithIndex f z = foldr (\(Tuple i x) y -> f i x y) z <<< mapWithIndex Tuple - foldlWithIndex f z = foldl (\y (Tuple i x) -> f i y x) z <<< mapWithIndex Tuple + foldrWithIndex f z = foldr (\(Tuple i x) y -> f i x y) z <<< mapWithIndex + Tuple + foldlWithIndex f z = foldl (\y (Tuple i x) -> f i y x) z <<< mapWithIndex + Tuple foldMapWithIndex = foldMapWithIndexDefaultR instance foldableWithIndexMaybe :: FoldableWithIndex Unit Maybe where @@ -156,17 +164,18 @@ instance foldableWithIndexConj :: FoldableWithIndex Unit Conj where foldlWithIndex f = foldl $ f unit foldMapWithIndex f = foldMap $ f unit -instance foldableWithIndexMultiplicative :: FoldableWithIndex Unit Multiplicative where +instance foldableWithIndexMultiplicative :: + FoldableWithIndex Unit Multiplicative where foldrWithIndex f = foldr $ f unit foldlWithIndex f = foldl $ f unit foldMapWithIndex f = foldMap $ f unit instance foldableWithIndexEither :: FoldableWithIndex Unit (Either a) where - foldrWithIndex _ z (Left _) = z + foldrWithIndex _ z (Left _) = z foldrWithIndex f z (Right x) = f unit x z - foldlWithIndex _ z (Left _) = z + foldlWithIndex _ z (Left _) = z foldlWithIndex f z (Right x) = f unit z x - foldMapWithIndex _ (Left _) = mempty + foldMapWithIndex _ (Left _) = mempty foldMapWithIndex f (Right x) = f unit x instance foldableWithIndexTuple :: FoldableWithIndex Unit (Tuple a) where @@ -184,27 +193,55 @@ instance foldableWithIndexConst :: FoldableWithIndex Void (Const a) where foldlWithIndex _ z _ = z foldMapWithIndex _ _ = mempty -instance foldableWithIndexProduct :: (FoldableWithIndex a f, FoldableWithIndex b g) => FoldableWithIndex (Either a b) (Product f g) where - foldrWithIndex f z (Product (Tuple fa ga)) = foldrWithIndex (f <<< Left) (foldrWithIndex (f <<< Right) z ga) fa - foldlWithIndex f z (Product (Tuple fa ga)) = foldlWithIndex (f <<< Right) (foldlWithIndex (f <<< Left) z fa) ga - foldMapWithIndex f (Product (Tuple fa ga)) = foldMapWithIndex (f <<< Left) fa <> foldMapWithIndex (f <<< Right) ga - -instance foldableWithIndexCoproduct :: (FoldableWithIndex a f, FoldableWithIndex b g) => FoldableWithIndex (Either a b) (Coproduct f g) where - foldrWithIndex f z = coproduct (foldrWithIndex (f <<< Left) z) (foldrWithIndex (f <<< Right) z) - foldlWithIndex f z = coproduct (foldlWithIndex (f <<< Left) z) (foldlWithIndex (f <<< Right) z) - foldMapWithIndex f = coproduct (foldMapWithIndex (f <<< Left)) (foldMapWithIndex (f <<< Right)) - -instance foldableWithIndexCompose :: (FoldableWithIndex a f, FoldableWithIndex b g) => FoldableWithIndex (Tuple a b) (Compose f g) where - foldrWithIndex f i (Compose fga) = foldrWithIndex (\a -> flip (foldrWithIndex (curry f a))) i fga - foldlWithIndex f i (Compose fga) = foldlWithIndex (foldlWithIndex <<< curry f) i fga - foldMapWithIndex f (Compose fga) = foldMapWithIndex (foldMapWithIndex <<< curry f) fga - -instance foldableWithIndexApp :: FoldableWithIndex a f => FoldableWithIndex a (App f) where +instance foldableWithIndexProduct :: + ( FoldableWithIndex a f + , FoldableWithIndex b g + ) => + FoldableWithIndex (Either a b) (Product f g) where + foldrWithIndex f z (Product (Tuple fa ga)) = foldrWithIndex (f <<< Left) + (foldrWithIndex (f <<< Right) z ga) + fa + foldlWithIndex f z (Product (Tuple fa ga)) = foldlWithIndex (f <<< Right) + (foldlWithIndex (f <<< Left) z fa) + ga + foldMapWithIndex f (Product (Tuple fa ga)) = foldMapWithIndex (f <<< Left) fa + <> foldMapWithIndex (f <<< Right) ga + +instance foldableWithIndexCoproduct :: + ( FoldableWithIndex a f + , FoldableWithIndex b g + ) => + FoldableWithIndex (Either a b) (Coproduct f g) where + foldrWithIndex f z = coproduct (foldrWithIndex (f <<< Left) z) + (foldrWithIndex (f <<< Right) z) + foldlWithIndex f z = coproduct (foldlWithIndex (f <<< Left) z) + (foldlWithIndex (f <<< Right) z) + foldMapWithIndex f = coproduct (foldMapWithIndex (f <<< Left)) + (foldMapWithIndex (f <<< Right)) + +instance foldableWithIndexCompose :: + ( FoldableWithIndex a f + , FoldableWithIndex b g + ) => + FoldableWithIndex (Tuple a b) (Compose f g) where + foldrWithIndex f i (Compose fga) = foldrWithIndex + (\a -> flip (foldrWithIndex (curry f a))) + i + fga + foldlWithIndex f i (Compose fga) = foldlWithIndex (foldlWithIndex <<< curry f) + i + fga + foldMapWithIndex f (Compose fga) = foldMapWithIndex + (foldMapWithIndex <<< curry f) + fga + +instance foldableWithIndexApp :: + FoldableWithIndex a f => + FoldableWithIndex a (App f) where foldrWithIndex f z (App x) = foldrWithIndex f z x foldlWithIndex f z (App x) = foldlWithIndex f z x foldMapWithIndex f (App x) = foldMapWithIndex f x - -- | Similar to 'foldlWithIndex', but the result is encapsulated in a monad. -- | -- | Note: this function is not generally stack-safe, e.g., for monads which @@ -287,7 +324,8 @@ surroundMapWithIndex -> f a -> m surroundMapWithIndex d t f = unwrap (foldMapWithIndex joined f) d - where joined i a = Endo \m -> d <> t i a <> m + where + joined i a = Endo \m -> d <> t i a <> m -- | `allWithIndex f` is the same as `and <<< mapWithIndex f`; map a function over the -- | structure, and then get the conjunction of the results. @@ -321,13 +359,13 @@ findWithIndex -> Maybe { index :: i, value :: a } findWithIndex p = foldlWithIndex go Nothing where - go - :: i - -> Maybe { index :: i, value :: a } - -> a - -> Maybe { index :: i, value :: a } - go i Nothing x | p i x = Just { index: i, value: x } - go _ r _ = r + go + :: i + -> Maybe { index :: i, value :: a } + -> a + -> Maybe { index :: i, value :: a } + go i Nothing x | p i x = Just { index: i, value: x } + go _ r _ = r -- | Try to find an element in a data structure which satisfies a predicate mapping -- | with access to the index. @@ -339,26 +377,32 @@ findMapWithIndex -> Maybe b findMapWithIndex f = foldlWithIndex go Nothing where - go - :: i - -> Maybe b - -> a - -> Maybe b - go i Nothing x = f i x - go _ r _ = r + go + :: i + -> Maybe b + -> a + -> Maybe b + go i Nothing x = f i x + go _ r _ = r -- | A default implementation of `foldr` using `foldrWithIndex` foldrDefault :: forall i f a b . FoldableWithIndex i f - => (a -> b -> b) -> b -> f a -> b + => (a -> b -> b) + -> b + -> f a + -> b foldrDefault f = foldrWithIndex (const f) -- | A default implementation of `foldl` using `foldlWithIndex` foldlDefault :: forall i f a b . FoldableWithIndex i f - => (b -> a -> b) -> b -> f a -> b + => (b -> a -> b) + -> b + -> f a + -> b foldlDefault f = foldlWithIndex (const f) -- | A default implementation of `foldMap` using `foldMapWithIndex` @@ -366,5 +410,7 @@ foldMapDefault :: forall i f a m . FoldableWithIndex i f => Monoid m - => (a -> m) -> f a -> m + => (a -> m) + -> f a + -> m foldMapDefault f = foldMapWithIndex (const f) diff --git a/src/Data/FunctorWithIndex.purs b/src/Data/FunctorWithIndex.purs index 9d9a48d..3221280 100644 --- a/src/Data/FunctorWithIndex.purs +++ b/src/Data/FunctorWithIndex.purs @@ -1,5 +1,7 @@ module Data.FunctorWithIndex - ( class FunctorWithIndex, mapWithIndex, mapDefault + ( class FunctorWithIndex + , mapWithIndex + , mapDefault ) where import Prelude @@ -35,7 +37,8 @@ import Data.Tuple (Tuple, curry) class Functor f <= FunctorWithIndex i f | f -> i where mapWithIndex :: forall a b. (i -> a -> b) -> f a -> f b -foreign import mapWithIndexArray :: forall a b. (Int -> a -> b) -> Array a -> Array b +foreign import mapWithIndexArray + :: forall a b. (Int -> a -> b) -> Array a -> Array b instance functorWithIndexArray :: FunctorWithIndex Int Array where mapWithIndex = mapWithIndexArray @@ -76,16 +79,34 @@ instance functorWithIndexIdentity :: FunctorWithIndex Unit Identity where instance functorWithIndexConst :: FunctorWithIndex Void (Const a) where mapWithIndex _ (Const x) = Const x -instance functorWithIndexProduct :: (FunctorWithIndex a f, FunctorWithIndex b g) => FunctorWithIndex (Either a b) (Product f g) where - mapWithIndex f (Product fga) = Product (bimap (mapWithIndex (f <<< Left)) (mapWithIndex (f <<< Right)) fga) - -instance functorWithIndexCoproduct :: (FunctorWithIndex a f, FunctorWithIndex b g) => FunctorWithIndex (Either a b) (Coproduct f g) where - mapWithIndex f (Coproduct e) = Coproduct (bimap (mapWithIndex (f <<< Left)) (mapWithIndex (f <<< Right)) e) - -instance functorWithIndexCompose :: (FunctorWithIndex a f, FunctorWithIndex b g) => FunctorWithIndex (Tuple a b) (Compose f g) where - mapWithIndex f (Compose fga) = Compose $ mapWithIndex (mapWithIndex <<< curry f) fga - -instance functorWithIndexApp :: FunctorWithIndex a f => FunctorWithIndex a (App f) where +instance functorWithIndexProduct :: + ( FunctorWithIndex a f + , FunctorWithIndex b g + ) => + FunctorWithIndex (Either a b) (Product f g) where + mapWithIndex f (Product fga) = Product + (bimap (mapWithIndex (f <<< Left)) (mapWithIndex (f <<< Right)) fga) + +instance functorWithIndexCoproduct :: + ( FunctorWithIndex a f + , FunctorWithIndex b g + ) => + FunctorWithIndex (Either a b) (Coproduct f g) where + mapWithIndex f (Coproduct e) = Coproduct + (bimap (mapWithIndex (f <<< Left)) (mapWithIndex (f <<< Right)) e) + +instance functorWithIndexCompose :: + ( FunctorWithIndex a f + , FunctorWithIndex b g + ) => + FunctorWithIndex (Tuple a b) (Compose f g) where + mapWithIndex f (Compose fga) = Compose $ mapWithIndex + (mapWithIndex <<< curry f) + fga + +instance functorWithIndexApp :: + FunctorWithIndex a f => + FunctorWithIndex a (App f) where mapWithIndex f (App x) = App $ mapWithIndex f x -- | A default implementation of Functor's `map` in terms of `mapWithIndex` diff --git a/src/Data/Semigroup/Foldable.purs b/src/Data/Semigroup/Foldable.purs index a7fdf36..ea52e5b 100644 --- a/src/Data/Semigroup/Foldable.purs +++ b/src/Data/Semigroup/Foldable.purs @@ -63,20 +63,35 @@ foldr1Default = flip (runFoldRight1 <<< foldMap1 mkFoldRight1) -- | Note: when defining a `Foldable1` instance, this function is unsafe to use -- | in combination with `foldMap1DefaultL`. foldl1Default :: forall t a. Foldable1 t => (a -> a -> a) -> t a -> a -foldl1Default = flip (runFoldRight1 <<< alaF Dual foldMap1 mkFoldRight1) <<< flip +foldl1Default = flip (runFoldRight1 <<< alaF Dual foldMap1 mkFoldRight1) <<< + flip -- | A default implementation of `foldMap1` using `foldr1`. -- | -- | Note: when defining a `Foldable1` instance, this function is unsafe to use -- | in combination with `foldr1Default`. -foldMap1DefaultR :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1DefaultR + :: forall t m a + . Foldable1 t + => Functor t + => Semigroup m + => (a -> m) + -> t a + -> m foldMap1DefaultR f = map f >>> foldr1 (<>) -- | A default implementation of `foldMap1` using `foldl1`. -- | -- | Note: when defining a `Foldable1` instance, this function is unsafe to use -- | in combination with `foldl1Default`. -foldMap1DefaultL :: forall t m a. Foldable1 t => Functor t => Semigroup m => (a -> m) -> t a -> m +foldMap1DefaultL + :: forall t m a + . Foldable1 t + => Functor t + => Semigroup m + => (a -> m) + -> t a + -> m foldMap1DefaultL f = map f >>> foldl1 (<>) instance foldableDual :: Foldable1 Dual where @@ -114,7 +129,8 @@ instance semigroupAct :: Apply f => Semigroup (Act f a) where -- | Traverse a data structure, performing some effects encoded by an -- | `Apply` instance at each value, ignoring the final result. -traverse1_ :: forall t f a b. Foldable1 t => Apply f => (a -> f b) -> t a -> f Unit +traverse1_ + :: forall t f a b. Foldable1 t => Apply f => (a -> f b) -> t a -> f Unit traverse1_ f t = unit <$ getAct (foldMap1 (Act <<< f) t) -- | A version of `traverse1_` with its arguments flipped. @@ -161,7 +177,10 @@ intercalateMap :: forall f m a . Foldable1 f => Semigroup m - => m -> (a -> m) -> f a -> m + => m + -> (a -> m) + -> f a + -> m intercalateMap j f foldable = joinee (foldMap1 (JoinWith <<< const <<< f) foldable) j @@ -169,7 +188,9 @@ intercalateMap j f foldable = data FoldRight1 a = FoldRight1 (a -> (a -> a -> a) -> a) a instance foldRight1Semigroup :: Semigroup (FoldRight1 a) where - append (FoldRight1 lf lr) (FoldRight1 rf rr) = FoldRight1 (\a f -> lf (f lr (rf a f)) f) rr + append (FoldRight1 lf lr) (FoldRight1 rf rr) = FoldRight1 + (\a f -> lf (f lr (rf a f)) f) + rr mkFoldRight1 :: forall a. a -> FoldRight1 a mkFoldRight1 = FoldRight1 const diff --git a/src/Data/Traversable.lua b/src/Data/Traversable.lua index 2592d76..3eaac2d 100644 --- a/src/Data/Traversable.lua +++ b/src/Data/Traversable.lua @@ -5,7 +5,7 @@ return { traverseArrayImpl = (function(apply) return function(map) return function(pure) - return function (appendArrays) + return function(appendArrays) return function(f) return function(array) local function go(bot, top) diff --git a/src/Data/Traversable.purs b/src/Data/Traversable.purs index c8342b0..26a73af 100644 --- a/src/Data/Traversable.purs +++ b/src/Data/Traversable.purs @@ -1,6 +1,9 @@ module Data.Traversable - ( class Traversable, traverse, sequence - , traverseDefault, sequenceDefault + ( class Traversable + , traverse + , sequence + , traverseDefault + , sequenceDefault , for , scanl , scanr @@ -114,9 +117,9 @@ foreign import traverseArrayImpl -> m (Array b) instance traversableMaybe :: Traversable Maybe where - traverse _ Nothing = pure Nothing + traverse _ Nothing = pure Nothing traverse f (Just x) = Just <$> f x - sequence Nothing = pure Nothing + sequence Nothing = pure Nothing sequence (Just x) = Just <$> x instance traversableFirst :: Traversable First where @@ -148,10 +151,10 @@ instance traversableMultiplicative :: Traversable Multiplicative where sequence (Multiplicative x) = Multiplicative <$> x instance traversableEither :: Traversable (Either a) where - traverse _ (Left x) = pure (Left x) + traverse _ (Left x) = pure (Left x) traverse f (Right x) = Right <$> f x sequence (Left x) = pure (Left x) - sequence (Right x) = Right <$> x + sequence (Right x) = Right <$> x instance traversableTuple :: Traversable (Tuple a) where traverse f (Tuple x y) = Tuple x <$> f y @@ -165,11 +168,20 @@ instance traversableConst :: Traversable (Const a) where traverse _ (Const x) = pure (Const x) sequence (Const x) = pure (Const x) -instance traversableProduct :: (Traversable f, Traversable g) => Traversable (Product f g) where - traverse f (Product (Tuple fa ga)) = lift2 product (traverse f fa) (traverse f ga) +instance traversableProduct :: + ( Traversable f + , Traversable g + ) => + Traversable (Product f g) where + traverse f (Product (Tuple fa ga)) = lift2 product (traverse f fa) + (traverse f ga) sequence (Product (Tuple fa ga)) = lift2 product (sequence fa) (sequence ga) -instance traversableCoproduct :: (Traversable f, Traversable g) => Traversable (Coproduct f g) where +instance traversableCoproduct :: + ( Traversable f + , Traversable g + ) => + Traversable (Coproduct f g) where traverse f = coproduct (map (Coproduct <<< Left) <<< traverse f) (map (Coproduct <<< Right) <<< traverse f) @@ -177,7 +189,11 @@ instance traversableCoproduct :: (Traversable f, Traversable g) => Traversable ( (map (Coproduct <<< Left) <<< sequence) (map (Coproduct <<< Right) <<< sequence) -instance traversableCompose :: (Traversable f, Traversable g) => Traversable (Compose f g) where +instance traversableCompose :: + ( Traversable f + , Traversable g + ) => + Traversable (Compose f g) where traverse f (Compose fga) = map Compose $ traverse (traverse f) fga sequence = traverse identity @@ -216,7 +232,8 @@ for x f = traverse f x -- | scanl (-) 10 [1,2,3] = [9,7,4] -- | ``` scanl :: forall a b f. Traversable f => (b -> a -> b) -> b -> f a -> f b -scanl f b0 xs = (mapAccumL (\b a -> let b' = f b a in { accum: b', value: b' }) b0 xs).value +scanl f b0 xs = + (mapAccumL (\b a -> let b' = f b a in { accum: b', value: b' }) b0 xs).value -- | Fold a data structure from the left, keeping all intermediate results -- | instead of only the final result. @@ -241,7 +258,8 @@ mapAccumL f s0 xs = stateL (traverse (\a -> StateL \s -> f s a) xs) s0 -- | scanr (flip (-)) 10 [1,2,3] = [4,5,7] -- | ``` scanr :: forall a b f. Traversable f => (a -> b -> b) -> b -> f a -> f b -scanr f b0 xs = (mapAccumR (\b a -> let b' = f a b in { accum: b', value: b' }) b0 xs).value +scanr f b0 xs = + (mapAccumR (\b a -> let b' = f a b in { accum: b', value: b' }) b0 xs).value -- | Fold a data structure from the right, keeping all intermediate results -- | instead of only the final result. diff --git a/src/Data/Traversable/Accum/Internal.purs b/src/Data/Traversable/Accum/Internal.purs index 9f9ae33..c675618 100644 --- a/src/Data/Traversable/Accum/Internal.purs +++ b/src/Data/Traversable/Accum/Internal.purs @@ -25,7 +25,6 @@ instance applyStateL :: Apply (StateL s) where instance applicativeStateL :: Applicative (StateL s) where pure a = StateL \s -> { accum: s, value: a } - newtype StateR s a = StateR (s -> Accum s a) stateR :: forall s a. StateR s a -> s -> Accum s a diff --git a/src/Data/TraversableWithIndex.purs b/src/Data/TraversableWithIndex.purs index f09d5e7..96878f1 100644 --- a/src/Data/TraversableWithIndex.purs +++ b/src/Data/TraversableWithIndex.purs @@ -1,5 +1,6 @@ -module Data.TraversableWithIndex - ( class TraversableWithIndex, traverseWithIndex +module Data.TraversableWithIndex + ( class TraversableWithIndex + , traverseWithIndex , traverseWithIndexDefault , forWithIndex , scanlWithIndex @@ -35,7 +36,6 @@ import Data.Traversable.Accum (Accum) import Data.Traversable.Accum.Internal (StateL(..), StateR(..), stateL, stateR) import Data.Tuple (Tuple(..), curry) - -- | A `Traversable` with an additional index. -- | A `TraversableWithIndex` instance must be compatible with its -- | `Traversable` instance @@ -52,8 +52,15 @@ import Data.Tuple (Tuple(..), curry) -- | ``` -- | -- | A default implementation is provided by `traverseWithIndexDefault`. -class (FunctorWithIndex i t, FoldableWithIndex i t, Traversable t) <= TraversableWithIndex i t | t -> i where - traverseWithIndex :: forall a b m. Applicative m => (i -> a -> m b) -> t a -> m (t b) +class + ( FunctorWithIndex i t + , FoldableWithIndex i t + , Traversable t + ) <= + TraversableWithIndex i t + | t -> i where + traverseWithIndex + :: forall a b m. Applicative m => (i -> a -> m b) -> t a -> m (t b) -- | A default implementation of `traverseWithIndex` using `sequence` and `mapWithIndex`. traverseWithIndexDefault @@ -89,11 +96,12 @@ instance traversableWithIndexConj :: TraversableWithIndex Unit Conj where instance traversableWithIndexDisj :: TraversableWithIndex Unit Disj where traverseWithIndex f = traverse $ f unit -instance traversableWithIndexMultiplicative :: TraversableWithIndex Unit Multiplicative where +instance traversableWithIndexMultiplicative :: + TraversableWithIndex Unit Multiplicative where traverseWithIndex f = traverse $ f unit instance traversableWithIndexEither :: TraversableWithIndex Unit (Either a) where - traverseWithIndex _ (Left x) = pure (Left x) + traverseWithIndex _ (Left x) = pure (Left x) traverseWithIndex f (Right x) = Right <$> f unit x instance traversableWithIndexTuple :: TraversableWithIndex Unit (Tuple a) where @@ -105,18 +113,36 @@ instance traversableWithIndexIdentity :: TraversableWithIndex Unit Identity wher instance traversableWithIndexConst :: TraversableWithIndex Void (Const a) where traverseWithIndex _ (Const x) = pure (Const x) -instance traversableWithIndexProduct :: (TraversableWithIndex a f, TraversableWithIndex b g) => TraversableWithIndex (Either a b) (Product f g) where - traverseWithIndex f (Product (Tuple fa ga)) = lift2 product (traverseWithIndex (f <<< Left) fa) (traverseWithIndex (f <<< Right) ga) - -instance traversableWithIndexCoproduct :: (TraversableWithIndex a f, TraversableWithIndex b g) => TraversableWithIndex (Either a b) (Coproduct f g) where +instance traversableWithIndexProduct :: + ( TraversableWithIndex a f + , TraversableWithIndex b g + ) => + TraversableWithIndex (Either a b) (Product f g) where + traverseWithIndex f (Product (Tuple fa ga)) = lift2 product + (traverseWithIndex (f <<< Left) fa) + (traverseWithIndex (f <<< Right) ga) + +instance traversableWithIndexCoproduct :: + ( TraversableWithIndex a f + , TraversableWithIndex b g + ) => + TraversableWithIndex (Either a b) (Coproduct f g) where traverseWithIndex f = coproduct (map (Coproduct <<< Left) <<< traverseWithIndex (f <<< Left)) (map (Coproduct <<< Right) <<< traverseWithIndex (f <<< Right)) -instance traversableWithIndexCompose :: (TraversableWithIndex a f, TraversableWithIndex b g) => TraversableWithIndex (Tuple a b) (Compose f g) where - traverseWithIndex f (Compose fga) = map Compose $ traverseWithIndex (traverseWithIndex <<< curry f) fga - -instance traversableWithIndexApp :: TraversableWithIndex a f => TraversableWithIndex a (App f) where +instance traversableWithIndexCompose :: + ( TraversableWithIndex a f + , TraversableWithIndex b g + ) => + TraversableWithIndex (Tuple a b) (Compose f g) where + traverseWithIndex f (Compose fga) = map Compose $ traverseWithIndex + (traverseWithIndex <<< curry f) + fga + +instance traversableWithIndexApp :: + TraversableWithIndex a f => + TraversableWithIndex a (App f) where traverseWithIndex f (App x) = App <$> traverseWithIndex f x -- | A version of `traverseWithIndex` with its arguments flipped. @@ -157,7 +183,10 @@ scanlWithIndex -> f a -> f b scanlWithIndex f b0 xs = - (mapAccumLWithIndex (\i b a -> let b' = f i b a in { accum: b', value: b' }) b0 xs).value + ( mapAccumLWithIndex (\i b a -> let b' = f i b a in { accum: b', value: b' }) + b0 + xs + ).value -- | Fold a data structure from the left with access to the indices, keeping -- | all intermediate results instead of only the final result. @@ -171,7 +200,9 @@ mapAccumLWithIndex -> s -> f a -> Accum s (f b) -mapAccumLWithIndex f s0 xs = stateL (traverseWithIndex (\i a -> StateL \s -> f i s a) xs) s0 +mapAccumLWithIndex f s0 xs = stateL + (traverseWithIndex (\i a -> StateL \s -> f i s a) xs) + s0 -- | Fold a data structure from the right with access to the indices, keeping -- | all intermediate results instead of only the final result. Note that the @@ -188,7 +219,10 @@ scanrWithIndex -> f a -> f b scanrWithIndex f b0 xs = - (mapAccumRWithIndex (\i b a -> let b' = f i a b in { accum: b', value: b' }) b0 xs).value + ( mapAccumRWithIndex (\i b a -> let b' = f i a b in { accum: b', value: b' }) + b0 + xs + ).value -- | Fold a data structure from the right with access to the indices, keeping -- | all intermediate results instead of only the final result. @@ -202,12 +236,16 @@ mapAccumRWithIndex -> s -> f a -> Accum s (f b) -mapAccumRWithIndex f s0 xs = stateR (traverseWithIndex (\i a -> StateR \s -> f i s a) xs) s0 +mapAccumRWithIndex f s0 xs = stateR + (traverseWithIndex (\i a -> StateR \s -> f i s a) xs) + s0 -- | A default implementation of `traverse` in terms of `traverseWithIndex` traverseDefault :: forall i t a b m . TraversableWithIndex i t => Applicative m - => (a -> m b) -> t a -> m (t b) + => (a -> m b) + -> t a + -> m (t b) traverseDefault f = traverseWithIndex (const f) diff --git a/test-regression/Main.purs b/test-regression/Main.purs index c188044..d9e04ad 100644 --- a/test-regression/Main.purs +++ b/test-regression/Main.purs @@ -19,7 +19,8 @@ main = do assertEqual { actual: traverse Just ([] :: Array Int), expected: Just [] } assertEqual { actual: traverse Just [ 1 ], expected: Just [ 1 ] } assertEqual { actual: traverse Just [ 1, 2, 3 ], expected: Just [ 1, 2, 3 ] } - assertEqual { actual: traverse Just [ 1, 2, 3, 4 ], expected: Just [ 1, 2, 3, 4 ] } + assertEqual + { actual: traverse Just [ 1, 2, 3, 4 ], expected: Just [ 1, 2, 3, 4 ] } assertEqual { actual: traverse Just [ 1, 2, 3, 4, 5, 6, 7, 8 ] , expected: Just [ 1, 2, 3, 4, 5, 6, 7, 8 ] diff --git a/test/Main.purs b/test/Main.purs index 3e9d914..20c8965 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -29,7 +29,8 @@ foreign import arrayReplicate :: forall a. Int -> a -> Array a foreign import data NEArray :: Type -> Type foreign import mkNEArray :: forall r a. r -> (NEArray a -> r) -> Array a -> r -foreign import foldMap1NEArray :: forall r a. (r -> r -> r) -> (a -> r) -> NEArray a -> r +foreign import foldMap1NEArray + :: forall r a. (r -> r -> r) -> (a -> r) -> NEArray a -> r instance foldableNEArray :: Foldable NEArray where foldMap = foldMap1NEArray append @@ -56,7 +57,7 @@ main = do log "Test foldableArray instance" testFoldableArrayWith 20 - assert $ foldMapDefaultL (\x -> [x]) [1, 2] == [1, 2] + assert $ foldMapDefaultL (\x -> [ x ]) [ 1, 2 ] == [ 1, 2 ] log "Test foldableArray instance is stack safe" testFoldableArrayWith 20_000 @@ -85,7 +86,7 @@ main = do log "Test foldrDefault is stack safe" testFoldableFoldrDefault 20_000 - foreachE [1,2,3,4,5,10,20] \i -> do + foreachE [ 1, 2, 3, 4, 5, 10, 20 ] \i -> do log $ "Test traversableArray instance with an array of size: " <> show i testTraversableArrayWith i @@ -106,9 +107,9 @@ main = do log "Test FoldableWithIndex laws for array instance" testFoldableWithIndexLawsOn - ["a", "b", "c"] - (\i x -> [Tuple i x]) - (\x -> [x]) + [ "a", "b", "c" ] + (\i x -> [ Tuple i x ]) + (\x -> [ x ]) log "Test traversableArrayWithIndex instance" testTraversableWithIndexArrayWith 20 @@ -138,32 +139,34 @@ main = do testBitraversableIOrWith BSD log "Test indexl" - assert $ indexl 2 [1, 5, 10] == Just 10 - assert $ indexl 0 [1, 5, 10] == Just 1 - assert $ indexl 9 [1, 5, 10] == Nothing + assert $ indexl 2 [ 1, 5, 10 ] == Just 10 + assert $ indexl 0 [ 1, 5, 10 ] == Just 1 + assert $ indexl 9 [ 1, 5, 10 ] == Nothing log "Test indexr" - assert $ indexr 2 [1, 5, 10] == Just 1 - assert $ indexr 0 [1, 5, 10] == Just 10 - assert $ indexr 9 [1, 5, 10] == Nothing + assert $ indexr 2 [ 1, 5, 10 ] == Just 1 + assert $ indexr 0 [ 1, 5, 10 ] == Just 10 + assert $ indexr 9 [ 1, 5, 10 ] == Nothing log "Test find" - assert $ find (_ == 10) [1, 5, 10] == Just 10 - assert $ find (\x -> x `mod` 2 == 0) [1, 4, 10] == Just 4 + assert $ find (_ == 10) [ 1, 5, 10 ] == Just 10 + assert $ find (\x -> x `mod` 2 == 0) [ 1, 4, 10 ] == Just 4 log "Test findWithIndex" assert $ - case findWithIndex (\i x -> i `mod` 2 == 0 && x `mod` 2 == 0) [1, 2, 4, 6] of + case + findWithIndex (\i x -> i `mod` 2 == 0 && x `mod` 2 == 0) [ 1, 2, 4, 6 ] + of Nothing -> false Just { index, value } -> index == 2 && value == 4 log "Test findMap" *> do let pred x = if x > 5 then Just (x * 100) else Nothing - assert $ findMap pred [1, 5, 10, 20] == Just 1000 + assert $ findMap pred [ 1, 5, 10, 20 ] == Just 1000 log "Test findMapWithIndex" *> do let pred i x = if x >= 5 && i >= 3 then Just { i, x } else Nothing - assert $ findMapWithIndex pred [1, 5, 10, 20] == Just { i: 3, x: 20 } + assert $ findMapWithIndex pred [ 1, 5, 10, 20 ] == Just { i: 3, x: 20 } log "Test maximum" assert $ maximum (arrayFrom1UpTo 10) == Just 10 @@ -171,7 +174,7 @@ main = do log "Test maximumBy" assert $ maximumBy (compare `on` abs) - (map (negate <<< toNumber) (arrayFrom1UpTo 10)) + (map (negate <<< toNumber) (arrayFrom1UpTo 10)) == Just (-10.0) log "Test minimum" @@ -180,54 +183,59 @@ main = do log "Test minimumBy" assert $ minimumBy (compare `on` abs) - (map (negate <<< toNumber) (arrayFrom1UpTo 10)) + (map (negate <<< toNumber) (arrayFrom1UpTo 10)) == Just (-1.0) log "Test null" assert $ null Nothing == true assert $ null (Just 1) == false assert $ null [] == true - assert $ null [0] == false - assert $ null [0,1] == false + assert $ null [ 0 ] == false + assert $ null [ 0, 1 ] == false log "Test length" assert $ length Nothing == 0 assert $ length (Just 1) == 1 assert $ length [] == 0 - assert $ length [1] == 1 - assert $ length [1, 2] == 2 + assert $ length [ 1 ] == 1 + assert $ length [ 1, 2 ] == 2 log "Test surroundMap" assert $ "*" == surroundMap "*" show ([] :: Array Int) - assert $ "*1*" == surroundMap "*" show [1] - assert $ "*1*2*" == surroundMap "*" show [1, 2] - assert $ "*1*2*3*" == surroundMap "*" show [1, 2, 3] + assert $ "*1*" == surroundMap "*" show [ 1 ] + assert $ "*1*2*" == surroundMap "*" show [ 1, 2 ] + assert $ "*1*2*3*" == surroundMap "*" show [ 1, 2, 3 ] log "Test surroundMapWithIndex" assert $ "*" == surroundMapWithIndex "*" (\i x -> show i <> x) [] - assert $ "*0a*" == surroundMapWithIndex "*" (\i x -> show i <> x) ["a"] - assert $ "*0a*1b*" == surroundMapWithIndex "*" (\i x -> show i <> x) ["a", "b"] - assert $ "*0a*1b*2c*" == surroundMapWithIndex "*" (\i x -> show i <> x) ["a", "b", "c"] + assert $ "*0a*" == surroundMapWithIndex "*" (\i x -> show i <> x) [ "a" ] + assert $ "*0a*1b*" == surroundMapWithIndex "*" (\i x -> show i <> x) + [ "a", "b" ] + assert $ "*0a*1b*2c*" == surroundMapWithIndex "*" (\i x -> show i <> x) + [ "a", "b", "c" ] log "Test Foldable1 defaults" - assert $ "(a(b(cd)))" == foldMap (foldr1 (\x y -> "(" <> x <> y <> ")")) (maybeMkNEArray ["a", "b", "c", "d"]) - assert $ "(((ab)c)d)" == foldMap (foldl1 (\x y -> "(" <> x <> y <> ")")) (maybeMkNEArray ["a", "b", "c", "d"]) + assert $ "(a(b(cd)))" == foldMap (foldr1 (\x y -> "(" <> x <> y <> ")")) + (maybeMkNEArray [ "a", "b", "c", "d" ]) + assert $ "(((ab)c)d)" == foldMap (foldl1 (\x y -> "(" <> x <> y <> ")")) + (maybeMkNEArray [ "a", "b", "c", "d" ]) log "Test maximumBy" assert $ - (Foldable1.maximumBy (compare `on` abs) <$> - (maybeMkNEArray (negate <<< toNumber <$> arrayFrom1UpTo 10))) + ( Foldable1.maximumBy (compare `on` abs) <$> + (maybeMkNEArray (negate <<< toNumber <$> arrayFrom1UpTo 10)) + ) == Just (-10.0) log "Test minimumBy" assert $ - (Foldable1.minimumBy (compare `on` abs) <$> - (maybeMkNEArray (negate <<< toNumber <$> arrayFrom1UpTo 10))) + ( Foldable1.minimumBy (compare `on` abs) <$> + (maybeMkNEArray (negate <<< toNumber <$> arrayFrom1UpTo 10)) + ) == Just (-1.0) log "All done!" - testFoldableFWith :: forall f . Foldable f @@ -260,13 +268,14 @@ testFoldableWithIndexFWith f n = do assert $ foldrWithIndex (\i x y -> (i + 1) * x + y) 0 dat == expectedSum assert $ foldlWithIndex (\i y x -> y + (i + 1) * x) 0 dat == expectedSum - assert $ foldMapWithIndex (\i x -> Additive $ (i + 1) * x) dat == Additive expectedSum + assert $ foldMapWithIndex (\i x -> Additive $ (i + 1) * x) dat == Additive + expectedSum testFoldableWithIndexArrayWith :: Int -> Effect Unit testFoldableWithIndexArrayWith = testFoldableWithIndexFWith arrayFrom1UpTo - data Tuple a b = Tuple a b + derive instance eqTuple :: (Eq a, Eq b) => Eq (Tuple a b) -- test whether foldable laws hold, using foldMap and ifoldMap @@ -296,8 +305,12 @@ testFoldableWithIndexLawsOn c f g = do -- These follow from the above laws, but they test whether ifoldlDefault and -- ifoldrDefault have been specified correctly. - assert $ foldMapWithIndex f c == foldlWithIndexDefault (\i y x -> y <> f i x) mempty c - assert $ foldMapWithIndex f c == foldrWithIndexDefault (\i x y -> f i x <> y) mempty c + assert $ foldMapWithIndex f c == foldlWithIndexDefault (\i y x -> y <> f i x) + mempty + c + assert $ foldMapWithIndex f c == foldrWithIndexDefault (\i x y -> f i x <> y) + mempty + c testTraversableFWith :: forall f @@ -313,10 +326,12 @@ testTraversableFWith f n = do _ <- traverse pure dat assert' "traverse Just == Just" $ traverse Just dat == Just dat - assert' "traverse pure == pure (Array)" $ traverse pure dat == [dat] + assert' "traverse pure == pure (Array)" $ traverse pure dat == [ dat ] when (len <= 10) do - result <- deferEff \_ -> traverse (\x -> [x,x]) dat == arrayReplicate (pow 2 len) dat + result <- deferEff \_ -> traverse (\x -> [ x, x ]) dat == arrayReplicate + (pow 2 len) + dat assert' "traverse with Array as underlying applicative" result assert' "traverse (const Nothing) == const Nothing" $ @@ -342,12 +357,14 @@ testTraversableWithIndexFWith testTraversableWithIndexFWith f n = do let dat = f n - assert $ traverseWithIndex (\i -> Just <<< Tuple i) dat == Just (mapWithIndex Tuple dat) + assert $ traverseWithIndex (\i -> Just <<< Tuple i) dat == Just + (mapWithIndex Tuple dat) assert $ traverseWithIndex (const Just) dat == traverse Just dat - assert $ traverseWithIndex (\i -> pure <<< Tuple i) dat == [mapWithIndex Tuple dat] + assert $ traverseWithIndex (\i -> pure <<< Tuple i) dat == + [ mapWithIndex Tuple dat ] assert $ traverseWithIndex (const pure :: Int -> Int -> Array Int) dat == - traverse pure dat + traverse pure dat testTraversableWithIndexArrayWith :: Int -> Effect Unit @@ -357,37 +374,44 @@ testTraversableWithIndexArrayWith = testTraversableWithIndexFWith arrayFrom1UpTo newtype FoldMapDefaultL a = FML (Array a) newtype FoldMapDefaultR a = FMR (Array a) -newtype FoldlDefault a = FLD (Array a) -newtype FoldrDefault a = FRD (Array a) +newtype FoldlDefault a = FLD (Array a) +newtype FoldrDefault a = FRD (Array a) + +instance eqFML :: (Eq a) => Eq (FoldMapDefaultL a) where + eq (FML l) (FML r) = l == r + +instance eqFMR :: (Eq a) => Eq (FoldMapDefaultR a) where + eq (FMR l) (FMR r) = l == r -instance eqFML :: (Eq a) => Eq (FoldMapDefaultL a) where eq (FML l) (FML r) = l == r -instance eqFMR :: (Eq a) => Eq (FoldMapDefaultR a) where eq (FMR l) (FMR r) = l == r -instance eqFLD :: (Eq a) => Eq (FoldlDefault a) where eq (FLD l) (FLD r) = l == r -instance eqFRD :: (Eq a) => Eq (FoldrDefault a) where eq (FRD l) (FRD r) = l == r +instance eqFLD :: (Eq a) => Eq (FoldlDefault a) where + eq (FLD l) (FLD r) = l == r + +instance eqFRD :: (Eq a) => Eq (FoldrDefault a) where + eq (FRD l) (FRD r) = l == r -- implemented `foldl` and `foldr`, but default `foldMap` using `foldl` instance foldableFML :: Foldable FoldMapDefaultL where - foldMap f = foldMapDefaultL f + foldMap f = foldMapDefaultL f foldl f u (FML a) = foldl f u a foldr f u (FML a) = foldr f u a -- implemented `foldl` and `foldr`, but default `foldMap`, using `foldr` instance foldableFMR :: Foldable FoldMapDefaultR where - foldMap f = foldMapDefaultR f + foldMap f = foldMapDefaultR f foldl f u (FMR a) = foldl f u a foldr f u (FMR a) = foldr f u a -- implemented `foldMap` and `foldr`, but default `foldMap` instance foldableDFL :: Foldable FoldlDefault where foldMap f (FLD a) = foldMap f a - foldl f u = foldlDefault f u + foldl f u = foldlDefault f u foldr f u (FLD a) = foldr f u a -- implemented `foldMap` and `foldl`, but default `foldr` instance foldableDFR :: Foldable FoldrDefault where foldMap f (FRD a) = foldMap f a foldl f u (FRD a) = foldl f u a - foldr f u = foldrDefault f u + foldr f u = foldrDefault f u testFoldableFoldMapDefaultL :: Int -> Effect Unit testFoldableFoldMapDefaultL = testFoldableFWith (FML <<< arrayFrom1UpTo) @@ -401,17 +425,22 @@ testFoldableFoldlDefault = testFoldableFWith (FLD <<< arrayFrom1UpTo) testFoldableFoldrDefault :: Int -> Effect Unit testFoldableFoldrDefault = testFoldableFWith (FRD <<< arrayFrom1UpTo) - -- structures for testing default `Traversable` implementations newtype TraverseDefault a = TD (Array a) newtype SequenceDefault a = SD (Array a) -instance eqTD :: (Eq a) => Eq (TraverseDefault a) where eq (TD l) (TD r) = l == r -instance eqSD :: (Eq a) => Eq (SequenceDefault a) where eq (SD l) (SD r) = l == r +instance eqTD :: (Eq a) => Eq (TraverseDefault a) where + eq (TD l) (TD r) = l == r + +instance eqSD :: (Eq a) => Eq (SequenceDefault a) where + eq (SD l) (SD r) = l == r + +instance functorTD :: Functor TraverseDefault where + map f (TD a) = TD (map f a) -instance functorTD :: Functor TraverseDefault where map f (TD a) = TD (map f a) -instance functorSD :: Functor SequenceDefault where map f (SD a) = SD (map f a) +instance functorSD :: Functor SequenceDefault where + map f (SD a) = SD (map f a) instance foldableTD :: Foldable TraverseDefault where foldMap f (TD a) = foldMap f a @@ -424,12 +453,12 @@ instance foldableSD :: Foldable SequenceDefault where foldl f u (SD a) = foldl f u a instance traversableTD :: Traversable TraverseDefault where - traverse f = traverseDefault f + traverse f = traverseDefault f sequence (TD a) = map TD (sequence a) instance traversableSD :: Traversable SequenceDefault where traverse f (SD a) = map SD (traverse f a) - sequence m = sequenceDefault m + sequence m = sequenceDefault m testTraverseDefault :: Int -> Effect Unit testTraverseDefault = testTraversableFWith (TD <<< arrayFrom1UpTo) @@ -437,43 +466,42 @@ testTraverseDefault = testTraversableFWith (TD <<< arrayFrom1UpTo) testSequenceDefault :: Int -> Effect Unit testSequenceDefault = testTraversableFWith (SD <<< arrayFrom1UpTo) - -- structure for testing bifoldable, picked `inclusive or` as it has both products and sums data IOr l r = Both l r | Fst l | Snd r instance eqIOr :: (Eq l, Eq r) => Eq (IOr l r) where eq (Both lFst lSnd) (Both rFst rSnd) = (lFst == rFst) && (lSnd == rSnd) - eq (Fst l) (Fst r) = l == r - eq (Snd l) (Snd r) = l == r - eq _ _ = false + eq (Fst l) (Fst r) = l == r + eq (Snd l) (Snd r) = l == r + eq _ _ = false instance bifoldableIOr :: Bifoldable IOr where bifoldr l r u (Both fst snd) = l fst (r snd u) - bifoldr l _ u (Fst fst) = l fst u - bifoldr _ r u (Snd snd) = r snd u + bifoldr l _ u (Fst fst) = l fst u + bifoldr _ r u (Snd snd) = r snd u bifoldl l r u (Both fst snd) = r (l u fst) snd - bifoldl l _ u (Fst fst) = l u fst - bifoldl _ r u (Snd snd) = r u snd + bifoldl l _ u (Fst fst) = l u fst + bifoldl _ r u (Snd snd) = r u snd bifoldMap l r (Both fst snd) = l fst <> r snd - bifoldMap l _ (Fst fst) = l fst - bifoldMap _ r (Snd snd) = r snd + bifoldMap l _ (Fst fst) = l fst + bifoldMap _ r (Snd snd) = r snd instance bifunctorIOr :: Bifunctor IOr where bimap f g (Both fst snd) = Both (f fst) (g snd) - bimap f _ (Fst fst) = Fst (f fst) - bimap _ g (Snd snd) = Snd (g snd) + bimap f _ (Fst fst) = Fst (f fst) + bimap _ g (Snd snd) = Snd (g snd) instance bitraversableIOr :: Bitraversable IOr where bitraverse f g (Both fst snd) = Both <$> f fst <*> g snd - bitraverse f _ (Fst fst) = Fst <$> f fst - bitraverse _ g (Snd snd) = Snd <$> g snd + bitraverse f _ (Fst fst) = Fst <$> f fst + bitraverse _ g (Snd snd) = Snd <$> g snd bisequence (Both fst snd) = Both <$> fst <*> snd - bisequence (Fst fst) = Fst <$> fst - bisequence (Snd snd) = Snd <$> snd + bisequence (Fst fst) = Fst <$> fst + bisequence (Snd snd) = Snd <$> snd testBifoldableIOrWith :: forall t @@ -486,16 +514,17 @@ testBifoldableIOrWith -> Effect Unit testBifoldableIOrWith lift fst snd u = do assert $ bifoldr (+) (*) u (lift $ Both fst snd) == fst + (snd * u) - assert $ bifoldr (+) (*) u (lift $ Fst fst) == fst + u - assert $ bifoldr (+) (*) u (lift $ Snd snd) == snd * u + assert $ bifoldr (+) (*) u (lift $ Fst fst) == fst + u + assert $ bifoldr (+) (*) u (lift $ Snd snd) == snd * u assert $ bifoldl (+) (*) u (lift $ Both fst snd) == (u + fst) * snd - assert $ bifoldl (+) (*) u (lift $ Fst fst) == u + fst - assert $ bifoldl (+) (*) u (lift $ Snd snd) == u * snd + assert $ bifoldl (+) (*) u (lift $ Fst fst) == u + fst + assert $ bifoldl (+) (*) u (lift $ Snd snd) == u * snd - assert $ bifoldMap Additive Additive (lift $ Both fst snd) == Additive (fst + snd) - assert $ bifoldMap Additive Additive (lift $ Fst fst) == Additive fst - assert $ bifoldMap Additive Additive (lift $ Snd snd) == Additive snd + assert $ bifoldMap Additive Additive (lift $ Both fst snd) == Additive + (fst + snd) + assert $ bifoldMap Additive Additive (lift $ Fst fst) == Additive fst + assert $ bifoldMap Additive Additive (lift $ Snd snd) == Additive snd testBitraversableIOrWith :: forall t @@ -505,57 +534,74 @@ testBitraversableIOrWith -> Effect Unit testBitraversableIOrWith lift = do let just a = Just (lift a) - assert $ bisequence (lift (Both (Just true) (Just false))) == just (Both true false) - assert $ bisequence (lift (Fst (Just true))) == just (Fst true :: IOr Boolean Boolean) - assert $ bisequence (lift (Snd (Just false))) == just (Snd false :: IOr Boolean Boolean) - assert $ bitraverse Just Just (lift (Both true false)) == just (Both true false) - assert $ bitraverse Just Just (lift (Fst true)) == just (Fst true :: IOr Boolean Boolean) - assert $ bitraverse Just Just (lift (Snd false)) == just (Snd false :: IOr Boolean Boolean) - + assert $ bisequence (lift (Both (Just true) (Just false))) == just + (Both true false) + assert $ bisequence (lift (Fst (Just true))) == just + (Fst true :: IOr Boolean Boolean) + assert $ bisequence (lift (Snd (Just false))) == just + (Snd false :: IOr Boolean Boolean) + assert $ bitraverse Just Just (lift (Both true false)) == just + (Both true false) + assert $ bitraverse Just Just (lift (Fst true)) == just + (Fst true :: IOr Boolean Boolean) + assert $ bitraverse Just Just (lift (Snd false)) == just + (Snd false :: IOr Boolean Boolean) -- structures for testing default `Bifoldable` implementations newtype BifoldMapDefaultL l r = BFML (IOr l r) newtype BifoldMapDefaultR l r = BFMR (IOr l r) -newtype BifoldlDefault l r = BFLD (IOr l r) -newtype BifoldrDefault l r = BFRD (IOr l r) +newtype BifoldlDefault l r = BFLD (IOr l r) +newtype BifoldrDefault l r = BFRD (IOr l r) + +instance eqBFML :: (Eq l, Eq r) => Eq (BifoldMapDefaultL l r) where + eq (BFML l) (BFML r) = l == r + +instance eqBFMR :: (Eq l, Eq r) => Eq (BifoldMapDefaultR l r) where + eq (BFMR l) (BFMR r) = l == r + +instance eqBFLD :: (Eq l, Eq r) => Eq (BifoldlDefault l r) where + eq (BFLD l) (BFLD r) = l == r -instance eqBFML :: (Eq l, Eq r) => Eq (BifoldMapDefaultL l r) where eq (BFML l) (BFML r) = l == r -instance eqBFMR :: (Eq l, Eq r) => Eq (BifoldMapDefaultR l r) where eq (BFMR l) (BFMR r) = l == r -instance eqBFLD :: (Eq l, Eq r) => Eq (BifoldlDefault l r) where eq (BFLD l) (BFLD r) = l == r -instance eqBFRD :: (Eq l, Eq r) => Eq (BifoldrDefault l r) where eq (BFRD l) (BFRD r) = l == r +instance eqBFRD :: (Eq l, Eq r) => Eq (BifoldrDefault l r) where + eq (BFRD l) (BFRD r) = l == r instance bifoldableBFML :: Bifoldable BifoldMapDefaultL where - bifoldMap f g m = bifoldMapDefaultL f g m + bifoldMap f g m = bifoldMapDefaultL f g m bifoldr f g u (BFML m) = bifoldr f g u m bifoldl f g u (BFML m) = bifoldl f g u m instance bifoldableBFMR :: Bifoldable BifoldMapDefaultR where - bifoldMap f g m = bifoldMapDefaultR f g m + bifoldMap f g m = bifoldMapDefaultR f g m bifoldr f g u (BFMR m) = bifoldr f g u m bifoldl f g u (BFMR m) = bifoldl f g u m instance bifoldableBFLD :: Bifoldable BifoldlDefault where bifoldMap f g (BFLD m) = bifoldMap f g m bifoldr f g u (BFLD m) = bifoldr f g u m - bifoldl f g u m = bifoldlDefault f g u m + bifoldl f g u m = bifoldlDefault f g u m instance bifoldableBFRD :: Bifoldable BifoldrDefault where bifoldMap f g (BFRD m) = bifoldMap f g m - bifoldr f g u m = bifoldrDefault f g u m + bifoldr f g u m = bifoldrDefault f g u m bifoldl f g u (BFRD m) = bifoldl f g u m - -- structures for testing default `Bitraversable` implementations newtype BitraverseDefault l r = BTD (IOr l r) newtype BisequenceDefault l r = BSD (IOr l r) -instance eqBTD :: (Eq l, Eq r) => Eq (BitraverseDefault l r) where eq (BTD l) (BTD r) = l == r -instance eqBSD :: (Eq l, Eq r) => Eq (BisequenceDefault l r) where eq (BSD l) (BSD r) = l == r +instance eqBTD :: (Eq l, Eq r) => Eq (BitraverseDefault l r) where + eq (BTD l) (BTD r) = l == r + +instance eqBSD :: (Eq l, Eq r) => Eq (BisequenceDefault l r) where + eq (BSD l) (BSD r) = l == r -instance bifunctorBTD :: Bifunctor BitraverseDefault where bimap f g (BTD m) = BTD (bimap f g m) -instance bifunctorBSD :: Bifunctor BisequenceDefault where bimap f g (BSD m) = BSD (bimap f g m) +instance bifunctorBTD :: Bifunctor BitraverseDefault where + bimap f g (BTD m) = BTD (bimap f g m) + +instance bifunctorBSD :: Bifunctor BisequenceDefault where + bimap f g (BSD m) = BSD (bimap f g m) instance bifoldableBTD :: Bifoldable BitraverseDefault where bifoldMap f g (BTD m) = bifoldMap f g m @@ -568,17 +614,16 @@ instance bifoldableBSD :: Bifoldable BisequenceDefault where bifoldl f g u (BSD m) = bifoldl f g u m instance bitraversableBTD :: Bitraversable BitraverseDefault where - bitraverse f g = bitraverseDefault f g + bitraverse f g = bitraverseDefault f g bisequence (BTD m) = map BTD (bisequence m) instance bitraversableBSD :: Bitraversable BisequenceDefault where bitraverse f g (BSD m) = map BSD (bitraverse f g m) - bisequence m = bisequenceDefault m - + bisequence m = bisequenceDefault m benchmarkDefaultFolds :: Effect Unit benchmarkDefaultFolds = do - let + let sm = arrayFrom1UpTo 1_000 m = arrayFrom1UpTo 10_000 lg = arrayFrom1UpTo 100_000 diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 0000000..0f57573 --- /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" + ]; +}