From 63dfbaa75710462a5651b8cc75c04d99f85f159c Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 29 Aug 2024 22:10:03 +0200 Subject: [PATCH 1/3] Add `lefts` and `rights` functions --- src/Data/Either.purs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/Data/Either.purs b/src/Data/Either.purs index 3940d93..b9476bb 100644 --- a/src/Data/Either.purs +++ b/src/Data/Either.purs @@ -2,6 +2,7 @@ module Data.Either where import Prelude +import Control.Bind (bindFlipped) import Control.Alt (class Alt, (<|>)) import Control.Extend (class Extend) import Data.Eq (class Eq1) @@ -253,6 +254,38 @@ fromRight' :: forall a b. (Unit -> b) -> Either a b -> b fromRight' _ (Right b) = b fromRight' default _ = default unit +-- | Keep from a `Monad` (typically an `Array`) of `Either` all +-- | the `Left` elements. +-- | +-- | For `Monad` with an order (such as `Array`), +-- | the initial order of the `Left` elements is preserved. +-- | +-- | A possible use case is to collect all errors of multiple `Either`. +-- | +-- | The type signature being more general than `Array`, it is possible to +-- | use it with other types such as `List`. +-- | +-- | ```purescript +-- | lefts [Left "Error 1", Right 42, Left "Error 2"] = ["Error 1", "Error 2"] +-- | ``` +lefts :: forall a b m. Monad m => Monoid (m a) => m (Either a b) -> m a +lefts = bindFlipped $ either pure (const mempty) + +-- | Keep from a `Monad` (typically an `Array`) of `Either` all +-- | the `Right` elements. +-- | +-- | For `Monad` with an order (such as `Array`), +-- | the initial order of the `Right` elements is preserved. +-- | +-- | The type signature being more general than `Array`, it is possible to +-- | use it with other types such as `List`. +-- | +-- | ```purescript +-- | rights [Left "Error 1", Right 42, Left "Error 2"] = [42] +-- | ``` +rights :: forall a b m. Monad m => Monoid (m b) => m (Either a b) -> m b +rights = bindFlipped $ either (const mempty) pure + -- | Takes a default and a `Maybe` value, if the value is a `Just`, turn it into -- | a `Right`, if the value is a `Nothing` use the provided default as a `Left` -- | From 12c723f0733d0c81c3166fcbde20c728c5060706 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 29 Aug 2024 22:13:36 +0200 Subject: [PATCH 2/3] Add tests for `lefts` and `rights` --- test/Main.purs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/Main.purs b/test/Main.purs index c878a67..9e62519 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,6 +2,7 @@ module Test.Main where import Prelude +import Data.Either (Either(..), lefts, rights) import Data.Either.Inject (inj, prj) import Data.Either.Nested (Either3, in1, in2, in3) import Data.Maybe (Maybe(..)) @@ -64,3 +65,29 @@ main = do { actual: prj (in3 100 :: MySum) , expected: Nothing :: Maybe Boolean } + log "Test lefts" + assertEqual + { actual: lefts [Left 1, Right 2, Left 3, Right 4] + , expected: [1, 3] + } + assertEqual + { actual: lefts [Right 2, Right 4] + , expected: [] :: Array Int + } + assertEqual + { actual: lefts [] + , expected: [] :: Array Int + } + log "Test rights" + assertEqual + { actual: rights [Left 1, Right 2, Left 3, Right 4] + , expected: [2, 4] + } + assertEqual + { actual: rights [Left 1, Left 3] + , expected: [] :: Array Int + } + assertEqual + { actual: rights [] + , expected: [] :: Array Int + } From 1d03e8cd67faf47ddf4d246950dbb8cd1836097e Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 29 Aug 2024 22:57:31 +0200 Subject: [PATCH 3/3] Log `lefts` and `rights` as new features --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73022e2..97a063f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Notable changes to this project are documented in this file. The format is based Breaking changes: New features: +- Add `lefts` and `rights` functions (#71 by @l-monnier) Bugfixes: