Skip to content

Commit

Permalink
Add Either.transposeOption (#4466)
Browse files Browse the repository at this point in the history
  • Loading branch information
vinassefranche authored and effect-bot committed Feb 19, 2025
1 parent 3470546 commit 85d6008
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-tables-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Add Either.transposeOption
36 changes: 36 additions & 0 deletions packages/effect/src/Either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { TypeLambda } from "./HKT.js"
import type { Inspectable } from "./Inspectable.js"
import * as doNotation from "./internal/doNotation.js"
import * as either from "./internal/either.js"
import * as option_ from "./internal/option.js"
import type { Option } from "./Option.js"
import type { Pipeable } from "./Pipeable.js"
import type { Predicate, Refinement } from "./Predicate.js"
Expand Down Expand Up @@ -966,3 +967,38 @@ export {
*/
let_ as let
}

/**
* Converts an `Option` of an `Either` into an `Either` of an `Option`.
*
* **Details**
*
* This function transforms an `Option<Either<A, E>>` into an
* `Either<Option<A>, E>`. If the `Option` is `None`, the resulting `Either`
* will be a `Right` with a `None` value. If the `Option` is `Some`, the
* inner `Either` will be executed, and its result wrapped in a `Some`.
*
* @example
* ```ts
* import { Effect, Either, Option } from "effect"
*
* // ┌─── Option<Either<number, never>>
* // ▼
* const maybe = Option.some(Either.right(42))
*
* // ┌─── Either<Option<number>, never, never>
* // ▼
* const result = Either.transposeOption(maybe)
*
* console.log(Effect.runSync(result))
* // Output: { _id: 'Option', _tag: 'Some', value: 42 }
* ```
*
* @since 3.14.0
* @category Optional Wrapping & Unwrapping
*/
export const transposeOption = <A = never, E = never>(
self: Option<Either<A, E>>
): Either<Option<A>, E> => {
return option_.isNone(self) ? right(option_.none) : map(self.value, option_.some)
}
17 changes: 17 additions & 0 deletions packages/effect/test/Effect/optional-wrapping-unwrapping.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assert, describe, it } from "@effect/vitest"
import * as Effect from "effect/Effect"
import * as Either from "effect/Either"
import * as Option from "effect/Option"

describe("Effect", () => {
Expand All @@ -17,3 +18,19 @@ describe("Effect", () => {
}))
})
})

describe("Either", () => {
describe("transposeOption", () => {
it.effect("None", () =>
Effect.gen(function*() {
const result = yield* Either.transposeOption(Option.none())
assert.ok(Option.isNone(result))
}))

it.effect("Some", () =>
Effect.gen(function*() {
const result = yield* Either.transposeOption(Option.some(Either.right(42)))
assert.deepStrictEqual(result, Option.some(42))
}))
})
})

0 comments on commit 85d6008

Please sign in to comment.