From 9e61e0bd2b476f9b151984872335391af635a768 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Thu, 15 Oct 2026 00:49:57 +0000 Subject: [PATCH 1/6] Migrate package and CI from Bower to Spago --- .github/workflows/ci.yml | 27 ++++++++++++--------------- .gitignore | 6 ++++-- .oxfmtrc.json | 3 +++ .tidyrc.json | 10 ++++++++++ CHANGELOG.md | 10 +++------- bower.json | 32 -------------------------------- package.json | 16 +++++++++------- spago.yaml | 34 ++++++++++++++++++++++++++++++++++ 8 files changed, 75 insertions(+), 63 deletions(-) create mode 100644 .oxfmtrc.json create mode 100644 .tidyrc.json delete mode 100644 bower.json create mode 100644 spago.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76a7124..d2aa6cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,30 +5,27 @@ on: branches: [main] pull_request: +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - uses: purescript-contrib/setup-purescript@main - with: - purescript: "unstable" + - uses: actions/checkout@v6 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v6 with: - node-version: "14.x" + node-version: "24" - name: Install dependencies - run: | - npm install -g bower - npm install - bower install --production + run: npm install - name: Build source - run: npm run-script build + run: npm run build - name: Run tests - run: | - bower install - npm run-script test --if-present + run: npm test + + - name: Check formatting + run: npm run format:check diff --git a/.gitignore b/.gitignore index 70df87e..6b169de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ .* !.gitignore !.github +!/.tidyrc.json +!/.oxfmtrc.json output generated-docs bower_components node_modules -package-lock.json -*.lock +/package-lock.json +/spago.lock diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..757fd64 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,3 @@ +{ + "trailingComma": "es5" +} diff --git a/.tidyrc.json b/.tidyrc.json new file mode 100644 index 0000000..9e39cf1 --- /dev/null +++ b/.tidyrc.json @@ -0,0 +1,10 @@ +{ + "importSort": "ide", + "importWrap": "source", + "indent": 2, + "operatorsFile": null, + "ribbon": 1, + "typeArrowPlacement": "first", + "unicode": "never", + "width": null +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 62126f0..6f41854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,12 @@ Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - -Breaking changes: - -New features: - -Bugfixes: +## [v5.0.1](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.1) Other improvements: +- Migrate from Bower/Pulp to Spago and update CI, tooling, and formatting. + ## [v5.0.0](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.0) - 2022-04-27 Breaking changes: diff --git a/bower.json b/bower.json deleted file mode 100644 index 83f75ca..0000000 --- a/bower.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "purescript-filterable", - "homepage": "https://github.com/purescript/purescript-filterable", - "description": "Classes for filterable and witherable data structures", - "author": "Liam Goodacre", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/purescript/purescript-filterable.git" - }, - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "output", - "test", - "bower.json", - "package.json" - ], - "dependencies": { - "purescript-foldable-traversable": "^6.0.0", - "purescript-identity": "^6.0.0", - "purescript-arrays": "^7.0.0", - "purescript-either": "^6.0.0", - "purescript-lists": "^7.0.0", - "purescript-ordered-collections": "^3.0.0" - }, - "devDependencies": { - "purescript-assert": "^6.0.0", - "purescript-console": "^6.0.0" - } -} diff --git a/package.json b/package.json index a7db390..4d6dfef 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "private": true, "scripts": { - "clean": "rimraf output && rimraf .pulp-cache", - "build": "pulp build -- --censor-lib --strict", - "test": "pulp test", - "build:docs": "rimraf docs && pulp docs" + "build": "spago build", + "test": "spago test", + "build:docs": "spago docs", + "format": "purs-tidy format-in-place src test && oxfmt --write .", + "format:check": "purs-tidy check src test && oxfmt --check ." }, "devDependencies": { - "pulp": "16.0.0-0", - "purescript-psa": "^0.8.2", - "rimraf": "^3.0.2" + "oxfmt": "^0.73.0", + "purescript": "^0.15.16", + "purs-tidy": "^0.11.1", + "spago": "^1.0.5" } } diff --git a/spago.yaml b/spago.yaml new file mode 100644 index 0000000..1efb75a --- /dev/null +++ b/spago.yaml @@ -0,0 +1,34 @@ +package: + name: filterable + description: Classes for filterable and witherable data structures + build: + strict: true + pedanticPackages: true + publish: + version: 5.0.1 + license: MIT + location: + githubOwner: purescript + githubRepo: purescript-filterable + dependencies: + - arrays: ">=7.0.0 <8.0.0" + - control: ">=6.0.0 <7.0.0" + - either: ">=6.0.0 <7.0.0" + - foldable-traversable: ">=6.0.0 <7.0.0" + - identity: ">=6.0.0 <7.0.0" + - lists: ">=7.0.0 <8.0.0" + - maybe: ">=6.0.0 <7.0.0" + - newtype: ">=5.0.0 <6.0.0" + - ordered-collections: ">=3.0.0 <4.0.0" + - prelude: ">=6.0.0 <7.0.0" + - st: ">=6.0.0 <7.0.0" + - tuples: ">=7.0.0 <8.0.0" + test: + main: Test.Main + strict: true + pedanticPackages: true + dependencies: + - assert: ">=6.0.0 <7.0.0" + - console: ">=6.0.0 <7.0.0" + - effect: ">=4.0.0 <5.0.0" +workspace: {} From 0993abc67cbab38e05f42726b42ea3ef2e168351 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Thu, 15 Oct 2026 00:51:26 +0000 Subject: [PATCH 2/6] Format PureScript and repository files --- CHANGELOG.md | 2 + src/Data/Compactable.purs | 117 +++++---- src/Data/Filterable.purs | 168 ++++++++----- src/Data/Witherable.purs | 148 ++++++++---- test/Main.purs | 490 +++++++++++++++++++++----------------- 5 files changed, 566 insertions(+), 359 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f41854..b9e533d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Other improvements: ## [v5.0.0](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.0) - 2022-04-27 Breaking changes: + - Update project and deps to PureScript v0.15.0 (#23 by @JordanMartinez) New features: @@ -22,6 +23,7 @@ Other improvements: ## [v4.0.1](https://github.com/purescript/purescript-filterable/releases/tag/v4.0.1) - 2021-04-19 Other improvements: + - Renamed default branch to `main` from `master` (@thomashoneyman) - Fix UnusedName warnings revealed by v0.14.1 PureScript release (#22 by @JordanMartinez) diff --git a/src/Data/Compactable.purs b/src/Data/Compactable.purs index 2e6be9d..cfabbac 100644 --- a/src/Data/Compactable.purs +++ b/src/Data/Compactable.purs @@ -64,53 +64,66 @@ import Prelude (class Ord, const, discard, unit, void, (<<<)) -- | - `compact (const Nothing <$> xs) ≡ empty` class Compactable f where - compact :: forall a. - f (Maybe a) -> f a - - separate :: forall l r. - f (Either l r) -> { left :: f l, right :: f r } - -compactDefault :: forall f a. Functor f => Compactable f => - f (Maybe a) -> f a + compact + :: forall a + . f (Maybe a) + -> f a + + separate + :: forall l r + . f (Either l r) + -> { left :: f l, right :: f r } + +compactDefault + :: forall f a + . Functor f + => Compactable f + => f (Maybe a) + -> f a compactDefault = _.right <<< separate <<< map (note unit) -separateDefault :: forall f l r. Functor f => Compactable f => - f (Either l r) -> { left :: f l, right :: f r} -separateDefault xs = { left: compact $ (hush <<< swapEither) <$> xs - , right: compact $ hush <$> xs - } +separateDefault + :: forall f l r + . Functor f + => Compactable f + => f (Either l r) + -> { left :: f l, right :: f r } +separateDefault xs = + { left: compact $ (hush <<< swapEither) <$> xs + , right: compact $ hush <$> xs + } where - swapEither e = case e of - Left x -> Right x - Right y -> Left y + swapEither e = case e of + Left x -> Right x + Right y -> Left y instance compactableMaybe :: Compactable Maybe where compact = join separate Nothing = { left: Nothing, right: Nothing } separate (Just e) = case e of - Left l -> { left: Just l, right: Nothing } + Left l -> { left: Just l, right: Nothing } Right r -> { left: Nothing, right: Just r } instance compactableEither :: Monoid m => Compactable (Either m) where compact (Left m) = Left m compact (Right m) = case m of - Just v -> Right v + Just v -> Right v Nothing -> Left mempty separate (Left x) = { left: Left x, right: Left x } separate (Right e) = case e of - Left l -> { left: Right l, right: Left mempty } + Left l -> { left: Right l, right: Left mempty } Right r -> { left: Left mempty, right: Right r } instance compactableArray :: Compactable Array where compact xs = ST.run do result <- STA.new - iter <- STAI.iterator (xs !! _) + iter <- STAI.iterator (xs !! _) STAI.iterate iter $ void <<< case _ of Nothing -> pure 0 - Just j -> STA.push j result + Just j -> STA.push j result STA.unsafeFreeze result @@ -120,45 +133,69 @@ instance compactableArray :: Compactable Array where iter <- STAI.iterator (xs !! _) STAI.iterate iter $ void <<< case _ of - Left l -> STA.push l ls + Left l -> STA.push l ls Right r -> STA.push r rs - {left: _, right: _} <$> STA.unsafeFreeze ls <*> STA.unsafeFreeze rs + { left: _, right: _ } <$> STA.unsafeFreeze ls <*> STA.unsafeFreeze rs instance compactableList :: Compactable List.List where compact = List.catMaybes - separate = foldl go { left: empty, right: empty } where + separate = foldl go { left: empty, right: empty } + where go acc = case _ of - Left l -> acc { left = acc.left <|> pure l } + Left l -> acc { left = acc.left <|> pure l } Right r -> acc { right = acc.right <|> pure r } instance compactableMap :: Ord k => Compactable (Map.Map k) where compact = foldr select Map.empty <<< mapToList where - select (Tuple k x) m = Map.alter (const x) k m + select (Tuple k x) m = Map.alter (const x) k m separate = foldr select { left: Map.empty, right: Map.empty } <<< mapToList where - select (Tuple k v) { left, right } = case v of - Left l -> { left: Map.insert k l left, right } - Right r -> { left: left, right: Map.insert k r right } - -mapToList :: forall k v. Ord k => - Map.Map k v -> List.List (Tuple k v) + select (Tuple k v) { left, right } = case v of + Left l -> { left: Map.insert k l left, right } + Right r -> { left: left, right: Map.insert k r right } + +mapToList + :: forall k v + . Ord k + => Map.Map k v + -> List.List (Tuple k v) mapToList = Map.toUnfoldable -applyMaybe :: forall f a b. Apply f => Compactable f => - f (a -> Maybe b) -> f a -> f b +applyMaybe + :: forall f a b + . Apply f + => Compactable f + => f (a -> Maybe b) + -> f a + -> f b applyMaybe p = compact <<< apply p -applyEither :: forall f a l r. Apply f => Compactable f => - f (a -> Either l r) -> f a -> { left :: f l, right :: f r } +applyEither + :: forall f a l r + . Apply f + => Compactable f + => f (a -> Either l r) + -> f a + -> { left :: f l, right :: f r } applyEither p = separate <<< apply p -bindMaybe :: forall m a b. Bind m => Compactable m => - m a -> (a -> m (Maybe b)) -> m b +bindMaybe + :: forall m a b + . Bind m + => Compactable m + => m a + -> (a -> m (Maybe b)) + -> m b bindMaybe x = compact <<< bind x -bindEither :: forall m a l r. Bind m => Compactable m => - m a -> (a -> m (Either l r)) -> { left :: m l, right :: m r } +bindEither + :: forall m a l r + . Bind m + => Compactable m + => m a + -> (a -> m (Either l r)) + -> { left :: m l, right :: m r } bindEither x = separate <<< bind x diff --git a/src/Data/Filterable.purs b/src/Data/Filterable.purs index 860d213..339e7f2 100644 --- a/src/Data/Filterable.purs +++ b/src/Data/Filterable.purs @@ -20,19 +20,19 @@ module Data.Filterable import Control.Bind ((=<<)) import Control.Category ((<<<)) -import Data.Array (partition, mapMaybe, filter) as Array +import Data.Array (filter, mapMaybe, partition) as Array import Data.Compactable (class Compactable, compact, separate) import Data.Either (Either(..)) import Data.Foldable (foldl, foldr) import Data.Functor (class Functor, map) import Data.HeytingAlgebra (not) import Data.List (List(..), filter, mapMaybe) as List -import Data.Map (Map, empty, insert, alter, toUnfoldable) as Map +import Data.Map (Map, alter, empty, insert, toUnfoldable) as Map import Data.Maybe (Maybe(..)) import Data.Monoid (class Monoid, mempty) import Data.Semigroup ((<>)) import Data.Tuple (Tuple(..)) -import Prelude (const, class Ord) +import Prelude (class Ord, const) -- | `Filterable` represents data structures which can be _partitioned_/_filtered_. -- | @@ -67,88 +67,144 @@ import Prelude (const, class Ord) -- | - `filterDefaultPartitionMap` -- | - `filterMapDefault` class (Compactable f, Functor f) <= Filterable f where - partitionMap :: forall a l r. - (a -> Either l r) -> f a -> { left :: f l, right :: f r } - - partition :: forall a. - (a -> Boolean) -> f a -> { no :: f a, yes :: f a } - - filterMap :: forall a b. - (a -> Maybe b) -> f a -> f b - - filter :: forall a. - (a -> Boolean) -> f a -> f a + partitionMap + :: forall a l r + . (a -> Either l r) + -> f a + -> { left :: f l, right :: f r } + + partition + :: forall a + . (a -> Boolean) + -> f a + -> { no :: f a, yes :: f a } + + filterMap + :: forall a b + . (a -> Maybe b) + -> f a + -> f b + + filter + :: forall a + . (a -> Boolean) + -> f a + -> f a -- | Upgrade a boolean-style predicate to an either-style predicate mapping. -eitherBool :: forall a. - (a -> Boolean) -> a -> Either a a +eitherBool + :: forall a + . (a -> Boolean) + -> a + -> Either a a eitherBool p x = if p x then Right x else Left x -- | Upgrade a boolean-style predicate to a maybe-style predicate mapping. -maybeBool :: forall a. - (a -> Boolean) -> a -> Maybe a +maybeBool + :: forall a + . (a -> Boolean) + -> a + -> Maybe a maybeBool p x = if p x then Just x else Nothing -- | A default implementation of `partitionMap` using `separate`. Note that this is -- | almost certainly going to be suboptimal compared to direct implementations. -partitionMapDefault :: forall f a l r. Filterable f => - (a -> Either l r) -> f a -> { left :: f l, right :: f r } +partitionMapDefault + :: forall f a l r + . Filterable f + => (a -> Either l r) + -> f a + -> { left :: f l, right :: f r } partitionMapDefault p = separate <<< map p -- | A default implementation of `partition` using `partitionMap`. -partitionDefault :: forall f a. Filterable f => - (a -> Boolean) -> f a -> { no :: f a, yes :: f a } +partitionDefault + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> { no :: f a, yes :: f a } partitionDefault p xs = - let o = partitionMap (eitherBool p) xs - in {no: o.left, yes: o.right} + let + o = partitionMap (eitherBool p) xs + in + { no: o.left, yes: o.right } -- | A default implementation of `partition` using `filter`. Note that this is -- | almost certainly going to be suboptimal compared to direct implementations. -partitionDefaultFilter :: forall f a. Filterable f => - (a -> Boolean) -> f a -> { no :: f a, yes :: f a } +partitionDefaultFilter + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> { no :: f a, yes :: f a } partitionDefaultFilter p xs = { yes: filter p xs, no: filter (not p) xs } -- | A default implementation of `filterMap` using `separate`. Note that this is -- | almost certainly going to be suboptimal compared to direct implementations. -filterMapDefault :: forall f a b. Filterable f => - (a -> Maybe b) -> f a -> f b +filterMapDefault + :: forall f a b + . Filterable f + => (a -> Maybe b) + -> f a + -> f b filterMapDefault p = compact <<< map p -- | A default implementation of `partition` using `filterMap`. Note that this -- | is almost certainly going to be suboptimal compared to direct -- | implementations. -partitionDefaultFilterMap :: forall f a. Filterable f => - (a -> Boolean) -> f a -> { no :: f a, yes :: f a } +partitionDefaultFilterMap + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> { no :: f a, yes :: f a } partitionDefaultFilterMap p xs = { yes: filterMap (maybeBool p) xs , no: filterMap (maybeBool (not p)) xs } -- | A default implementation of `filter` using `filterMap`. -filterDefault :: forall f a. Filterable f => - (a -> Boolean) -> f a -> f a +filterDefault + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> f a filterDefault = filterMap <<< maybeBool -- | A default implementation of `filter` using `partition`. -filterDefaultPartition :: forall f a. Filterable f => - (a -> Boolean) -> f a -> f a +filterDefaultPartition + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> f a filterDefaultPartition p xs = (partition p xs).yes -- | A default implementation of `filter` using `partitionMap`. -filterDefaultPartitionMap :: forall f a. Filterable f => - (a -> Boolean) -> f a -> f a +filterDefaultPartitionMap + :: forall f a + . Filterable f + => (a -> Boolean) + -> f a + -> f a filterDefaultPartitionMap p xs = (partitionMap (eitherBool p) xs).right -- | Filter out all values. -cleared :: forall f a b. Filterable f => - f a -> f b +cleared + :: forall f a b + . Filterable f + => f a + -> f b cleared = filterMap (const Nothing) instance filterableArray :: Filterable Array where - partitionMap p = foldl go {left: [], right: []} where + partitionMap p = foldl go { left: [], right: [] } + where go acc x = case p x of - Left l -> acc { left = acc.left <> [l] } - Right r -> acc { right = acc.right <> [r] } + Left l -> acc { left = acc.left <> [ l ] } + Right r -> acc { right = acc.right <> [ r ] } partition = Array.partition @@ -187,17 +243,17 @@ instance filterableList :: Filterable List.List where -- partitionMap :: forall a l r. (a -> Either l r) -> List a -> { left :: List l, right :: List r } partitionMap p xs = foldr select { left: List.Nil, right: List.Nil } xs where - select x { left, right } = case p x of - Left l -> { left: List.Cons l left, right } - Right r -> { left, right: List.Cons r right } + select x { left, right } = case p x of + Left l -> { left: List.Cons l left, right } + Right r -> { left, right: List.Cons r right } -- partition :: forall a. (a -> Boolean) -> List a -> { no :: List a, yes :: List a } partition p xs = foldr select { no: List.Nil, yes: List.Nil } xs where - -- select :: (a -> Boolean) -> a -> { no :: List a, yes :: List a } -> { no :: List a, yes :: List a } - select x { no, yes } = if p x - then { no, yes: List.Cons x yes } - else { no: List.Cons x no, yes } + -- select :: (a -> Boolean) -> a -> { no :: List a, yes :: List a } -> { no :: List a, yes :: List a } + select x { no, yes } = + if p x then { no, yes: List.Cons x yes } + else { no: List.Cons x no, yes } -- filterMap :: forall a b. (a -> Maybe b) -> List a -> List b filterMap p = List.mapMaybe p @@ -209,21 +265,21 @@ instance filterableMap :: Ord k => Filterable (Map.Map k) where partitionMap p xs = foldr select { left: Map.empty, right: Map.empty } (toList xs) where - toList :: forall v. Map.Map k v -> List.List (Tuple k v) - toList = Map.toUnfoldable + toList :: forall v. Map.Map k v -> List.List (Tuple k v) + toList = Map.toUnfoldable - select (Tuple k x) { left, right } = case p x of - Left l -> { left: Map.insert k l left, right } - Right r -> { left, right: Map.insert k r right } + select (Tuple k x) { left, right } = case p x of + Left l -> { left: Map.insert k l left, right } + Right r -> { left, right: Map.insert k r right } partition p = partitionDefault p filterMap p xs = foldr select Map.empty (toList xs) where - toList :: forall v. Map.Map k v -> List.List (Tuple k v) - toList = Map.toUnfoldable + toList :: forall v. Map.Map k v -> List.List (Tuple k v) + toList = Map.toUnfoldable - select (Tuple k x) m = Map.alter (const (p x)) k m + select (Tuple k x) m = Map.alter (const (p x)) k m filter p = filterDefault p diff --git a/src/Data/Witherable.purs b/src/Data/Witherable.purs index 1dfa232..8445ba5 100644 --- a/src/Data/Witherable.purs +++ b/src/Data/Witherable.purs @@ -12,8 +12,8 @@ module Data.Witherable , module Data.Filterable ) where -import Control.Applicative (class Applicative, (<*>), pure) -import Control.Category ((<<<), identity) +import Control.Applicative (class Applicative, pure, (<*>)) +import Control.Category (identity, (<<<)) import Data.Compactable (compact, separate) import Data.Either (Either(..)) import Data.Filterable (class Filterable) @@ -57,45 +57,84 @@ import Prelude (class Ord) -- | - `filterMapByWither` -- | - `traverseByWither` class (Filterable t, Traversable t) <= Witherable t where - wilt :: forall m a l r. Applicative m => - (a -> m (Either l r)) -> t a -> m { left :: t l, right :: t r } - - wither :: forall m a b. Applicative m => - (a -> m (Maybe b)) -> t a -> m (t b) + wilt + :: forall m a l r + . Applicative m + => (a -> m (Either l r)) + -> t a + -> m { left :: t l, right :: t r } + + wither + :: forall m a b + . Applicative m + => (a -> m (Maybe b)) + -> t a + -> m (t b) -- | A default implementation of `wilt` using `separate` -wiltDefault :: forall t m a l r. Witherable t => Applicative m => - (a -> m (Either l r)) -> t a -> m { left :: t l, right :: t r } +wiltDefault + :: forall t m a l r + . Witherable t + => Applicative m + => (a -> m (Either l r)) + -> t a + -> m { left :: t l, right :: t r } wiltDefault p = map separate <<< traverse p -- | A default implementation of `wither` using `compact`. -witherDefault :: forall t m a b. Witherable t => Applicative m => - (a -> m (Maybe b)) -> t a -> m (t b) +witherDefault + :: forall t m a b + . Witherable t + => Applicative m + => (a -> m (Maybe b)) + -> t a + -> m (t b) witherDefault p = map compact <<< traverse p -- | A default implementation of `partitionMap` given a `Witherable`. -partitionMapByWilt :: forall t a l r. Witherable t => - (a -> Either l r) -> t a -> { left :: t l, right :: t r } +partitionMapByWilt + :: forall t a l r + . Witherable t + => (a -> Either l r) + -> t a + -> { left :: t l, right :: t r } partitionMapByWilt p = unwrap <<< wilt (Identity <<< p) -- | A default implementation of `filterMap` given a `Witherable`. -filterMapByWither :: forall t a b. Witherable t => - (a -> Maybe b) -> t a -> t b +filterMapByWither + :: forall t a b + . Witherable t + => (a -> Maybe b) + -> t a + -> t b filterMapByWither p = unwrap <<< wither (Identity <<< p) -- | A default implementation of `traverse` given a `Witherable`. -traverseByWither :: forall t m a b. Witherable t => Applicative m => - (a -> m b) -> t a -> m (t b) +traverseByWither + :: forall t m a b + . Witherable t + => Applicative m + => (a -> m b) + -> t a + -> m (t b) traverseByWither f = wither (map Just <<< f) -- | Partition between `Left` and `Right` values - with effects in `m`. -wilted :: forall t m l r. Witherable t => Applicative m => - t (m (Either l r)) -> m { left :: t l, right :: t r } +wilted + :: forall t m l r + . Witherable t + => Applicative m + => t (m (Either l r)) + -> m { left :: t l, right :: t r } wilted = wilt identity -- | Filter out all the `Nothing` values - with effects in `m`. -withered :: forall t m x. Witherable t => Applicative m => - t (m (Maybe x)) -> m (t x) +withered + :: forall t m x + . Witherable t + => Applicative m + => t (m (Maybe x)) + -> m (t x) withered = wither identity instance witherableArray :: Witherable Array where @@ -103,47 +142,54 @@ instance witherableArray :: Witherable Array where wither = witherDefault instance witherableList :: Witherable List where - wilt p = map rev <<< List.foldl go (pure { left: Nil, right: Nil }) where + wilt p = map rev <<< List.foldl go (pure { left: Nil, right: Nil }) + where rev { left, right } = { left: List.reverse left, right: List.reverse right } - go acc x = (\{left, right} -> - case _ of - Left l -> { left: l : left, right } - Right r -> { left, right: r : right } + go acc x = + ( \{ left, right } -> + case _ of + Left l -> { left: l : left, right } + Right r -> { left, right: r : right } ) <$> acc <*> p x - wither p = map List.reverse <<< List.foldl go (pure Nil) where - go acc x = (\comp -> - case _ of - Nothing -> comp - Just j -> j : comp + wither p = map List.reverse <<< List.foldl go (pure Nil) + where + go acc x = + ( \comp -> + case _ of + Nothing -> comp + Just j -> j : comp ) <$> acc <*> p x instance witherableMap :: Ord k => Witherable (Map.Map k) where wilt p = List.foldl go (pure { left: Map.empty, right: Map.empty }) <<< toList where - toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) - toList = Map.toUnfoldable - - go acc (Tuple k x) = (\{left, right} -> - case _ of - Left l -> { left: Map.insert k l left, right } - Right r -> { left, right: Map.insert k r right } - ) <$> acc <*> p x + toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) + toList = Map.toUnfoldable + + go acc (Tuple k x) = + ( \{ left, right } -> + case _ of + Left l -> { left: Map.insert k l left, right } + Right r -> { left, right: Map.insert k r right } + ) <$> acc <*> p x wither p = List.foldl go (pure Map.empty) <<< toList where - toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) - toList = Map.toUnfoldable - - go acc (Tuple k x) = (\comp -> - case _ of - Nothing -> comp - Just j -> Map.insert k j comp - ) <$> acc <*> p x + toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) + toList = Map.toUnfoldable + + go acc (Tuple k x) = + ( \comp -> + case _ of + Nothing -> comp + Just j -> Map.insert k j comp + ) <$> acc <*> p x instance witherableMaybe :: Witherable Maybe where wilt _ Nothing = pure { left: Nothing, right: Nothing } - wilt p (Just x) = map convert (p x) where + wilt p (Just x) = map convert (p x) + where convert (Left l) = { left: Just l, right: Nothing } convert (Right r) = { left: Nothing, right: Just r } @@ -152,11 +198,13 @@ instance witherableMaybe :: Witherable Maybe where instance witherableEither :: Monoid m => Witherable (Either m) where wilt _ (Left el) = pure { left: Left el, right: Left el } - wilt p (Right er) = map convert (p er) where + wilt p (Right er) = map convert (p er) + where convert (Left l) = { left: Right l, right: Left mempty } convert (Right r) = { left: Left mempty, right: Right r } wither _ (Left el) = pure (Left el) - wither p (Right er) = map convert (p er) where + wither p (Right er) = map convert (p er) + where convert Nothing = Left mempty convert (Just r) = Right r diff --git a/test/Main.purs b/test/Main.purs index 08bf482..984d8a3 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -19,270 +19,334 @@ testCompactable :: Effect Unit testCompactable = do log "Test compactableMaybe instance" *> do let parts1 = separate $ Just ((Left 1) :: Either Int Int) - assertEqual { actual: parts1.left - , expected: Just 1 - } - assertEqual { actual: parts1.right - , expected: Nothing - } + assertEqual + { actual: parts1.left + , expected: Just 1 + } + assertEqual + { actual: parts1.right + , expected: Nothing + } let parts2 = separate $ Just ((Right 2) :: Either Int Int) - assertEqual { actual: parts2.left - , expected: Nothing - } - assertEqual { actual: parts2.right - , expected: Just 2 - } + assertEqual + { actual: parts2.left + , expected: Nothing + } + assertEqual + { actual: parts2.right + , expected: Just 2 + } let parts3 = separate $ (Nothing :: Maybe (Either Int Int)) - assertEqual { actual: parts3.left - , expected: Nothing - } - assertEqual { actual: parts3.right - , expected: Nothing - } + assertEqual + { actual: parts3.left + , expected: Nothing + } + assertEqual + { actual: parts3.right + , expected: Nothing + } log "Text compactableEither instance" *> do - assertEqual { actual: compact (Left [1] :: Either (Array Int) (Maybe Int)) - , expected: Left [1] - } + assertEqual + { actual: compact (Left [ 1 ] :: Either (Array Int) (Maybe Int)) + , expected: Left [ 1 ] + } - assertEqual { actual: compact (Right Nothing :: Either (Array Int) (Maybe Int)) - , expected: Left [] - } + assertEqual + { actual: compact (Right Nothing :: Either (Array Int) (Maybe Int)) + , expected: Left [] + } - assertEqual { actual: compact (Right (Just 3) :: Either (Array Int) (Maybe Int)) - , expected: Right 3 - } + assertEqual + { actual: compact (Right (Just 3) :: Either (Array Int) (Maybe Int)) + , expected: Right 3 + } - let parts1 = separate (Left [1] :: Either (Array Int) (Either Int Int)) - assertEqual { actual: parts1.left - , expected: Left [1] - } - assertEqual { actual: parts1.right - , expected: Left [1] - } + let parts1 = separate (Left [ 1 ] :: Either (Array Int) (Either Int Int)) + assertEqual + { actual: parts1.left + , expected: Left [ 1 ] + } + assertEqual + { actual: parts1.right + , expected: Left [ 1 ] + } let parts2 = separate (Right (Left 2) :: Either (Array Int) (Either Int Int)) - assertEqual { actual: parts2.left - , expected: Right 2 - } - assertEqual { actual: parts2.right - , expected: Left [] - } + assertEqual + { actual: parts2.left + , expected: Right 2 + } + assertEqual + { actual: parts2.right + , expected: Left [] + } let parts3 = separate (Right (Right 3) :: Either (Array Int) (Either Int Int)) - assertEqual { actual: parts3.left - , expected: Left [] - } - assertEqual { actual: parts3.right - , expected: Right 3 - } + assertEqual + { actual: parts3.left + , expected: Left [] + } + assertEqual + { actual: parts3.right + , expected: Right 3 + } log "Test compactableArray instance" *> do - let testList = [Left 1, Right 2, Left 3, Right 4, Left 5, Right 6, Left 7, Right 8] + let testList = [ Left 1, Right 2, Left 3, Right 4, Left 5, Right 6, Left 7, Right 8 ] let parts = separate testList - assertEqual { actual: parts.left - , expected: [1, 3, 5, 7] - } - assertEqual { actual: parts.right - , expected: [2, 4, 6, 8] - } + assertEqual + { actual: parts.left + , expected: [ 1, 3, 5, 7 ] + } + assertEqual + { actual: parts.right + , expected: [ 2, 4, 6, 8 ] + } log "Test compactableList instance" *> do let testList = (Left 1 : Right 2 : Left 3 : Right 4 : Left 5 : Right 6 : Left 7 : Right 8 : Nil) let parts = separate testList - assertEqual { actual: parts.left - , expected: 1 : 3 : 5 : 7 : Nil - } - assertEqual { actual: parts.right - , expected: 2 : 4 : 6 : 8 : Nil - } + assertEqual + { actual: parts.left + , expected: 1 : 3 : 5 : 7 : Nil + } + assertEqual + { actual: parts.right + , expected: 2 : 4 : 6 : 8 : Nil + } log "Test compactableMap instance" *> do let m = Map.fromFoldable - assertEqual { actual: compact $ m [1 /\ Just 1, 2 /\ Nothing, 3 /\ Just 3, 4 /\ Nothing] - , expected: m [1 /\ 1, 3 /\ 3] - } + assertEqual + { actual: compact $ m [ 1 /\ Just 1, 2 /\ Nothing, 3 /\ Just 3, 4 /\ Nothing ] + , expected: m [ 1 /\ 1, 3 /\ 3 ] + } - let parts = separate $ m [1 /\ Left 1, 2 /\ Right 2, 3 /\ Left 3, 4 /\ Right 4] - assertEqual { actual: parts.left - , expected: m [1 /\ 1, 3 /\ 3] - } - assertEqual { actual: parts.right - , expected: m [2 /\ 2, 4 /\ 4] - } + let parts = separate $ m [ 1 /\ Left 1, 2 /\ Right 2, 3 /\ Left 3, 4 /\ Right 4 ] + assertEqual + { actual: parts.left + , expected: m [ 1 /\ 1, 3 /\ 3 ] + } + assertEqual + { actual: parts.right + , expected: m [ 2 /\ 2, 4 /\ 4 ] + } testFilterable :: Effect Unit testFilterable = do log "Test filterableMaybe instance" *> do - assertEqual { actual: filterMap pred (Just 6) - , expected: Just 60 - } - assertEqual { actual: filterMap pred (Just 5) - , expected: Nothing - } - assertEqual { actual: filterMap pred Nothing - , expected: Nothing - } + assertEqual + { actual: filterMap pred (Just 6) + , expected: Just 60 + } + assertEqual + { actual: filterMap pred (Just 5) + , expected: Nothing + } + assertEqual + { actual: filterMap pred Nothing + , expected: Nothing + } - assertEqual { actual: filter (_ > 5) (Just 6) - , expected: Just 6 - } - assertEqual { actual: filter (_ > 5) (Just 5) - , expected: Nothing - } - assertEqual { actual: filter (_ > 5) Nothing - , expected: Nothing - } + assertEqual + { actual: filter (_ > 5) (Just 6) + , expected: Just 6 + } + assertEqual + { actual: filter (_ > 5) (Just 5) + , expected: Nothing + } + assertEqual + { actual: filter (_ > 5) Nothing + , expected: Nothing + } log "Test filterableList instance" *> do let testlist = (1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : Nil) - assertEqual { actual: filterMap pred testlist - , expected: 60 : 70 : 80 : 90 : Nil - } - assertEqual { actual: filter (_ > 5) testlist - , expected: 6 : 7 : 8 : 9 : Nil - } - assertEqual { actual: partition (_ > 5) testlist - , expected: { no: (1 : 2 : 3 : 4 : 5 : Nil), yes: (6 : 7 : 8 : 9 : Nil) } - } - assertEqual { actual: (partitionMap Right $ (1 : 2 : 3 : 4 : 5 : Nil)).right - , expected: 1 : 2 : 3 : 4 : 5 : Nil - } - assertEqual { actual: (partitionMap Left $ (1 : 2 : 3 : 4 : 5 : Nil)).left - , expected: 1 : 2 : 3 : 4 : 5 : Nil - } + assertEqual + { actual: filterMap pred testlist + , expected: 60 : 70 : 80 : 90 : Nil + } + assertEqual + { actual: filter (_ > 5) testlist + , expected: 6 : 7 : 8 : 9 : Nil + } + assertEqual + { actual: partition (_ > 5) testlist + , expected: { no: (1 : 2 : 3 : 4 : 5 : Nil), yes: (6 : 7 : 8 : 9 : Nil) } + } + assertEqual + { actual: (partitionMap Right $ (1 : 2 : 3 : 4 : 5 : Nil)).right + , expected: 1 : 2 : 3 : 4 : 5 : Nil + } + assertEqual + { actual: (partitionMap Left $ (1 : 2 : 3 : 4 : 5 : Nil)).left + , expected: 1 : 2 : 3 : 4 : 5 : Nil + } log "Test filterableArray instance" *> do - assertEqual { actual: filterMap pred [1,2,3,4,5,6,7,8,9] - , expected: [60,70,80,90] - } - assertEqual { actual: filter (_ > 5) [1,2,3,4,5,6,7,8,9] - , expected: [6,7,8,9] - } - assertEqual { actual: partition (_ > 5) [1,2,3,4,5,6,7,8,9] - , expected: { no: [1,2,3,4,5], yes: [6,7,8,9] } - } + assertEqual + { actual: filterMap pred [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + , expected: [ 60, 70, 80, 90 ] + } + assertEqual + { actual: filter (_ > 5) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + , expected: [ 6, 7, 8, 9 ] + } + assertEqual + { actual: partition (_ > 5) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + , expected: { no: [ 1, 2, 3, 4, 5 ], yes: [ 6, 7, 8, 9 ] } + } log "Test filterableMap instance" *> do let predE x = if x > 5 then Right (x * 10) else Left x let m = Map.fromFoldable - let xs = m [4 /\ 4, 5 /\ 5, 6 /\ 6, 7 /\ 7] - assertEqual { actual: filterMap pred xs - , expected: m [6 /\ 60, 7 /\ 70] - } - assertEqual { actual: filter (_ > 5) xs - , expected: m [6 /\ 6, 7 /\ 7] - } - assertEqual { actual: partition (_ > 5) xs - , expected: { no: m [4 /\ 4, 5 /\ 5], yes: m [6 /\ 6, 7 /\ 7] } - } - assertEqual { actual: partitionMap predE xs - , expected: { left: m [4 /\ 4, 5 /\ 5], right: m [6 /\ 60, 7 /\ 70] } - } + let xs = m [ 4 /\ 4, 5 /\ 5, 6 /\ 6, 7 /\ 7 ] + assertEqual + { actual: filterMap pred xs + , expected: m [ 6 /\ 60, 7 /\ 70 ] + } + assertEqual + { actual: filter (_ > 5) xs + , expected: m [ 6 /\ 6, 7 /\ 7 ] + } + assertEqual + { actual: partition (_ > 5) xs + , expected: { no: m [ 4 /\ 4, 5 /\ 5 ], yes: m [ 6 /\ 6, 7 /\ 7 ] } + } + assertEqual + { actual: partitionMap predE xs + , expected: { left: m [ 4 /\ 4, 5 /\ 5 ], right: m [ 6 /\ 60, 7 /\ 70 ] } + } where - pred x = if x > 5 then Just (x * 10) else Nothing + pred x = if x > 5 then Just (x * 10) else Nothing testWitherable :: Effect Unit testWitherable = do - log "Test witherableMaybe instance" *> do - assertEqual { actual: map _.right (wilt predE (Just 6)) - , expected: Identity (Just 60) - } - assertEqual { actual: map _.left (wilt predE (Just 5)) - , expected: Identity (Just 5) - } - assertEqual { actual: map _.right (wilt predE Nothing) - , expected: Identity Nothing - } + log "Test witherableMaybe instance" *> do + assertEqual + { actual: map _.right (wilt predE (Just 6)) + , expected: Identity (Just 60) + } + assertEqual + { actual: map _.left (wilt predE (Just 5)) + , expected: Identity (Just 5) + } + assertEqual + { actual: map _.right (wilt predE Nothing) + , expected: Identity Nothing + } - assertEqual { actual: wither predM (Just 6) - , expected: Identity (Just 60) - } - assertEqual { actual: wither predM (Just 5) - , expected: Identity Nothing - } - assertEqual { actual: wither predM Nothing - , expected: Identity Nothing - } + assertEqual + { actual: wither predM (Just 6) + , expected: Identity (Just 60) + } + assertEqual + { actual: wither predM (Just 5) + , expected: Identity Nothing + } + assertEqual + { actual: wither predM Nothing + , expected: Identity Nothing + } - log "Test witherableEither instance" *> do - assertEqual { actual: map _.right (wilt predE (Right 6 :: Either (Array Int) Int)) - , expected: Identity (Right 60) - } - assertEqual { actual: map _.left (wilt predE (Right 5 :: Either (Array Int) Int)) - , expected: Identity (Right 5) - } - assertEqual { actual: map _.right (wilt predE (Left [] :: Either (Array Int) Int)) - , expected: Identity (Left []) - } + log "Test witherableEither instance" *> do + assertEqual + { actual: map _.right (wilt predE (Right 6 :: Either (Array Int) Int)) + , expected: Identity (Right 60) + } + assertEqual + { actual: map _.left (wilt predE (Right 5 :: Either (Array Int) Int)) + , expected: Identity (Right 5) + } + assertEqual + { actual: map _.right (wilt predE (Left [] :: Either (Array Int) Int)) + , expected: Identity (Left []) + } - assertEqual { actual: wither predM (Just 6) - , expected: Identity (Just 60) - } - assertEqual { actual: wither predM (Just 5) - , expected: Identity Nothing - } - assertEqual { actual: wither predM Nothing - , expected: Identity Nothing - } + assertEqual + { actual: wither predM (Just 6) + , expected: Identity (Just 60) + } + assertEqual + { actual: wither predM (Just 5) + , expected: Identity Nothing + } + assertEqual + { actual: wither predM Nothing + , expected: Identity Nothing + } - log "Test witherableList instance" *> do - let testlist = (1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : Nil) - let resultWilt = wilt predE testlist - assertEqual { actual: map _.right resultWilt - , expected: Identity (60 : 70 : 80 : 90 : Nil) - } - assertEqual { actual: map _.left resultWilt - , expected: Identity (1 : 2 : 3 : 4 : 5 : Nil) - } - assertEqual { actual: map _.right (wilt predE Nil) - , expected: Identity Nil - } + log "Test witherableList instance" *> do + let testlist = (1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : Nil) + let resultWilt = wilt predE testlist + assertEqual + { actual: map _.right resultWilt + , expected: Identity (60 : 70 : 80 : 90 : Nil) + } + assertEqual + { actual: map _.left resultWilt + , expected: Identity (1 : 2 : 3 : 4 : 5 : Nil) + } + assertEqual + { actual: map _.right (wilt predE Nil) + , expected: Identity Nil + } - assertEqual { actual: wither predM testlist - , expected: Identity (60 : 70 : 80 : 90 : Nil) - } - assertEqual { actual: wither predM Nil - , expected: Identity Nil - } + assertEqual + { actual: wither predM testlist + , expected: Identity (60 : 70 : 80 : 90 : Nil) + } + assertEqual + { actual: wither predM Nil + , expected: Identity Nil + } - log "Test witherableArray instance" *> do - let testarray = [1, 2, 3, 4, 5, 6, 7, 8, 9] - let resultWilt = wilt predE testarray - assertEqual { actual: map _.right resultWilt - , expected: Identity [60, 70, 80, 90] - } - assertEqual { actual: map _.left resultWilt - , expected: Identity [1, 2, 3, 4, 5] - } - assertEqual { actual: map _.right (wilt predE []) - , expected: Identity [] - } + log "Test witherableArray instance" *> do + let testarray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + let resultWilt = wilt predE testarray + assertEqual + { actual: map _.right resultWilt + , expected: Identity [ 60, 70, 80, 90 ] + } + assertEqual + { actual: map _.left resultWilt + , expected: Identity [ 1, 2, 3, 4, 5 ] + } + assertEqual + { actual: map _.right (wilt predE []) + , expected: Identity [] + } - assertEqual { actual: wither predM testarray - , expected: Identity [60, 70, 80, 90] - } - assertEqual { actual: wither predM [], expected: Identity [] } + assertEqual + { actual: wither predM testarray + , expected: Identity [ 60, 70, 80, 90 ] + } + assertEqual { actual: wither predM [], expected: Identity [] } - log "Test witherableMap instance" *> do - let m = Map.fromFoldable - let xs = m [4 /\ 4, 5 /\ 5, 6 /\ 6, 7 /\ 7] - let resultWilt = wilt predE xs - assertEqual { actual: map _.right resultWilt - , expected: Identity (m [6 /\ 60, 7 /\ 70]) - } - assertEqual { actual: map _.left resultWilt - , expected: Identity (m [4 /\ 4, 5 /\ 5]) - } + log "Test witherableMap instance" *> do + let m = Map.fromFoldable + let xs = m [ 4 /\ 4, 5 /\ 5, 6 /\ 6, 7 /\ 7 ] + let resultWilt = wilt predE xs + assertEqual + { actual: map _.right resultWilt + , expected: Identity (m [ 6 /\ 60, 7 /\ 70 ]) + } + assertEqual + { actual: map _.left resultWilt + , expected: Identity (m [ 4 /\ 4, 5 /\ 5 ]) + } - assertEqual { actual: wither predM xs - , expected: Identity (m [6 /\ 60, 7 /\ 70]) - } + assertEqual + { actual: wither predM xs + , expected: Identity (m [ 6 /\ 60, 7 /\ 70 ]) + } - where - predM x = if x > 5 then Identity (Just (x * 10)) else Identity Nothing - predE x = if x > 5 then Identity (Right (x * 10)) else Identity (Left x) + where + predM x = if x > 5 then Identity (Just (x * 10)) else Identity Nothing + predE x = if x > 5 then Identity (Right (x * 10)) else Identity (Left x) main :: Effect Unit main = do From 93ff2d7f1d3a2f7166103bed389db78b7fcc3545 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Thu, 15 Oct 2026 00:52:48 +0000 Subject: [PATCH 3/6] Credit migration pull request in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e533d..a4ee3fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Notable changes to this project are documented in this file. The format is based Other improvements: -- Migrate from Bower/Pulp to Spago and update CI, tooling, and formatting. +- Migrate from Bower/Pulp to Spago and update CI, tooling, and formatting (#25 by @thomashoneyman) ## [v5.0.0](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.0) - 2022-04-27 From 21c265408a064673cfdc7d9464330a16f363c5d3 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Thu, 15 Oct 2026 21:26:06 +0000 Subject: [PATCH 4/6] Prepare changelog release date and unreleased section --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4ee3fa..1b4214d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,17 @@ Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v5.0.1](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.1) +## [Unreleased] + +Breaking changes: + +New features: + +Bugfixes: + +Other improvements: + +## [v5.0.1](https://github.com/purescript/purescript-filterable/releases/tag/v5.0.1) - 2026-10-17 Other improvements: From a92253cd2fe85b8a4e1a12cabe76900f61fba254 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Sat, 17 Oct 2026 13:04:44 +0000 Subject: [PATCH 5/6] Apply reviewed PureScript layout conventions --- src/Data/Compactable.purs | 29 +++++++------- src/Data/Filterable.purs | 41 ++++++++++---------- src/Data/Witherable.purs | 79 ++++++++++++++++++++------------------- 3 files changed, 79 insertions(+), 70 deletions(-) diff --git a/src/Data/Compactable.purs b/src/Data/Compactable.purs index cfabbac..7641d54 100644 --- a/src/Data/Compactable.purs +++ b/src/Data/Compactable.purs @@ -100,21 +100,24 @@ separateDefault xs = instance compactableMaybe :: Compactable Maybe where compact = join - separate Nothing = { left: Nothing, right: Nothing } - separate (Just e) = case e of - Left l -> { left: Just l, right: Nothing } - Right r -> { left: Nothing, right: Just r } + separate = case _ of + Nothing -> { left: Nothing, right: Nothing } + Just e -> case e of + Left l -> { left: Just l, right: Nothing } + Right r -> { left: Nothing, right: Just r } instance compactableEither :: Monoid m => Compactable (Either m) where - compact (Left m) = Left m - compact (Right m) = case m of - Just v -> Right v - Nothing -> Left mempty - - separate (Left x) = { left: Left x, right: Left x } - separate (Right e) = case e of - Left l -> { left: Right l, right: Left mempty } - Right r -> { left: Left mempty, right: Right r } + compact = case _ of + Left m -> Left m + Right m -> case m of + Just v -> Right v + Nothing -> Left mempty + + separate = case _ of + Left x -> { left: Left x, right: Left x } + Right e -> case e of + Left l -> { left: Right l, right: Left mempty } + Right r -> { left: Left mempty, right: Right r } instance compactableArray :: Compactable Array where compact xs = ST.run do diff --git a/src/Data/Filterable.purs b/src/Data/Filterable.purs index 339e7f2..3e91bc4 100644 --- a/src/Data/Filterable.purs +++ b/src/Data/Filterable.purs @@ -124,11 +124,9 @@ partitionDefault => (a -> Boolean) -> f a -> { no :: f a, yes :: f a } -partitionDefault p xs = - let - o = partitionMap (eitherBool p) xs - in - { no: o.left, yes: o.right } +partitionDefault p xs = do + let o = partitionMap (eitherBool p) xs + { no: o.left, yes: o.right } -- | A default implementation of `partition` using `filter`. Note that this is -- | almost certainly going to be suboptimal compared to direct implementations. @@ -213,10 +211,11 @@ instance filterableArray :: Filterable Array where filter = Array.filter instance filterableMaybe :: Filterable Maybe where - partitionMap _ Nothing = { left: Nothing, right: Nothing } - partitionMap p (Just x) = case p x of - Left a -> { left: Just a, right: Nothing } - Right b -> { left: Nothing, right: Just b } + partitionMap p = case _ of + Nothing -> { left: Nothing, right: Nothing } + Just x -> case p x of + Left a -> { left: Just a, right: Nothing } + Right b -> { left: Nothing, right: Just b } partition p = partitionDefault p @@ -225,17 +224,19 @@ instance filterableMaybe :: Filterable Maybe where filter p = filterDefault p instance filterableEither :: Monoid m => Filterable (Either m) where - partitionMap _ (Left x) = { left: Left x, right: Left x } - partitionMap p (Right x) = case p x of - Left a -> { left: Right a, right: Left mempty } - Right b -> { left: Left mempty, right: Right b } + partitionMap p = case _ of + Left x -> { left: Left x, right: Left x } + Right x -> case p x of + Left a -> { left: Right a, right: Left mempty } + Right b -> { left: Left mempty, right: Right b } partition p = partitionDefault p - filterMap _ (Left l) = Left l - filterMap p (Right r) = case p r of - Nothing -> Left mempty - Just x -> Right x + filterMap p = case _ of + Left l -> Left l + Right r -> case p r of + Nothing -> Left mempty + Just x -> Right x filter p = filterDefault p @@ -252,8 +253,10 @@ instance filterableList :: Filterable List.List where where -- select :: (a -> Boolean) -> a -> { no :: List a, yes :: List a } -> { no :: List a, yes :: List a } select x { no, yes } = - if p x then { no, yes: List.Cons x yes } - else { no: List.Cons x no, yes } + if p x then + { no, yes: List.Cons x yes } + else + { no: List.Cons x no, yes } -- filterMap :: forall a b. (a -> Maybe b) -> List a -> List b filterMap p = List.mapMaybe p diff --git a/src/Data/Witherable.purs b/src/Data/Witherable.purs index 8445ba5..8efb010 100644 --- a/src/Data/Witherable.purs +++ b/src/Data/Witherable.purs @@ -145,21 +145,19 @@ instance witherableList :: Witherable List where wilt p = map rev <<< List.foldl go (pure { left: Nil, right: Nil }) where rev { left, right } = { left: List.reverse left, right: List.reverse right } - go acc x = - ( \{ left, right } -> - case _ of - Left l -> { left: l : left, right } - Right r -> { left, right: r : right } - ) <$> acc <*> p x + go acc x = add <$> acc <*> p x + where + add { left, right } = case _ of + Left l -> { left: l : left, right } + Right r -> { left, right: r : right } wither p = map List.reverse <<< List.foldl go (pure Nil) where - go acc x = - ( \comp -> - case _ of - Nothing -> comp - Just j -> j : comp - ) <$> acc <*> p x + go acc x = add <$> acc <*> p x + where + add comp = case _ of + Nothing -> comp + Just j -> j : comp instance witherableMap :: Ord k => Witherable (Map.Map k) where wilt p = List.foldl go (pure { left: Map.empty, right: Map.empty }) <<< toList @@ -167,44 +165,49 @@ instance witherableMap :: Ord k => Witherable (Map.Map k) where toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) toList = Map.toUnfoldable - go acc (Tuple k x) = - ( \{ left, right } -> - case _ of - Left l -> { left: Map.insert k l left, right } - Right r -> { left, right: Map.insert k r right } - ) <$> acc <*> p x + go acc (Tuple k x) = add <$> acc <*> p x + where + add { left, right } = case _ of + Left l -> { left: Map.insert k l left, right } + Right r -> { left, right: Map.insert k r right } wither p = List.foldl go (pure Map.empty) <<< toList where toList :: forall v. Ord k => Map.Map k v -> List.List (Tuple k v) toList = Map.toUnfoldable - go acc (Tuple k x) = - ( \comp -> - case _ of - Nothing -> comp - Just j -> Map.insert k j comp - ) <$> acc <*> p x + go acc (Tuple k x) = add <$> acc <*> p x + where + add comp = case _ of + Nothing -> comp + Just j -> Map.insert k j comp instance witherableMaybe :: Witherable Maybe where - wilt _ Nothing = pure { left: Nothing, right: Nothing } - wilt p (Just x) = map convert (p x) + wilt p = case _ of + Nothing -> pure { left: Nothing, right: Nothing } + Just x -> map convert (p x) where - convert (Left l) = { left: Just l, right: Nothing } - convert (Right r) = { left: Nothing, right: Just r } + convert = case _ of + Left l -> { left: Just l, right: Nothing } + Right r -> { left: Nothing, right: Just r } - wither _ Nothing = pure Nothing - wither p (Just x) = p x + wither p = case _ of + Nothing -> pure Nothing + Just x -> p x instance witherableEither :: Monoid m => Witherable (Either m) where - wilt _ (Left el) = pure { left: Left el, right: Left el } - wilt p (Right er) = map convert (p er) + wilt p = case _ of + Left el -> pure { left: Left el, right: Left el } + Right er -> map convert (p er) where - convert (Left l) = { left: Right l, right: Left mempty } - convert (Right r) = { left: Left mempty, right: Right r } + convert = case _ of + Left l -> { left: Right l, right: Left mempty } + Right r -> { left: Left mempty, right: Right r } - wither _ (Left el) = pure (Left el) - wither p (Right er) = map convert (p er) + wither p = case _ of + Left el -> pure (Left el) + Right er -> map convert (p er) where - convert Nothing = Left mempty - convert (Just r) = Right r + convert = case _ of + Nothing -> Left mempty + Just r -> Right r From bc4340255a6a153ef662a4851cf04fec89d47587 Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Sat, 17 Oct 2026 16:21:52 +0000 Subject: [PATCH 6/6] Link Unreleased changelog comparison --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b4214d..d8cfd2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [Unreleased](https://github.com/purescript/purescript-filterable/compare/v5.0.1...HEAD) Breaking changes: