Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add requireSomeWith #303

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion gitbook/result/requireFunctions.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ let result : Result<unit, string> =

## requireSome

Converts an Option to a Result, using the given error if None.
Converts an Option to a Result, using the given function to supply an error if None.

### Function Signature

Expand Down Expand Up @@ -96,6 +96,38 @@ let result : Result<unit, string> =
// Error "Value must be Some"
```

## requireSomeWith

Converts an Option to a Result, using the given function to supply an error if None.

### Function Signature

```fsharp
'a -> 'b option -> Result<'b, 'a>
```

### Examples

#### Example 1

```fsharp
let result : Result<unit, string> =
Some 1
|> Result.requireSomeWith (fun () -> "Value must be Some")

// Ok ()
```

#### Example 2

```fsharp
let result : Result<unit, string> =
None
|> Result.requireSomeWith (fun () -> "Value must be Some")

// Error "Value must be Some"
```

## requireNone

Converts an Option to a Result, using the given error if Some.
Expand Down
6 changes: 5 additions & 1 deletion src/FsToolkit.ErrorHandling.JobResult/JobResult.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace FsToolkit.ErrorHandling
namespace FsToolkit.ErrorHandling

open Hopac
open Hopac.Infixes
Expand Down Expand Up @@ -124,6 +124,10 @@ module JobResult =
option
|> Job.map (Result.requireSome error)

let inline requireSomeWith ifErrorThunk option =
option
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Doc comments

|> Job.map (Result.requireSomeWith ifErrorThunk)

// Converts an job-wrapped Option to a Result, using the given error if Some.
let inline requireNone error option =
option
Expand Down
7 changes: 7 additions & 0 deletions src/FsToolkit.ErrorHandling/AsyncResult.fs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ module AsyncResult =
value
|> Async.map (Result.requireSome error)

let inline requireSomeWith
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Doc comments

(ifErrorThunk: unit -> 'error)
(value: Async<'ok option>)
: Async<Result<'ok, 'error>> =
value
|> Async.map (Result.requireSomeWith ifErrorThunk)

// Converts an async-wrapped Option to a Result, using the given error if Some.
let inline requireNone
(error: 'error)
Expand Down
16 changes: 16 additions & 0 deletions src/FsToolkit.ErrorHandling/Result.fs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,22 @@ module Result =
| Some x -> Ok x
| None -> Error error

/// <summary>
/// Returns the contained value if <c>Some</c>, otherwise evaluates <param name="ifErrorThunk"/> and returns the value.
///
/// Documentation is found here: <href>https://demystifyfp.gitbook.io/fstoolkit-errorhandling/fstoolkit.errorhandling/result/others#requireSomeWith</href>
/// </summary>
/// <param name="ifErrorThunk">The function to evaluate if the result is <c>None</c>.</param>
/// <param name="option">The input option.</param>
/// <returns>The contained value if <c>Some</c>, otherwise the result of evaluating <paramref name="ifErrorThunk"/>.</returns>
let inline requireSomeWith
(ifErrorThunk: unit -> 'error)
(option: 'ok option)
: Result<'ok, 'error> =
match option with
| Some x -> Ok x
| None -> Error(ifErrorThunk ())

/// <summary>
/// Requires a value to be <c>None</c>, otherwise returns an error result.
///
Expand Down
4 changes: 4 additions & 0 deletions src/FsToolkit.ErrorHandling/TaskResult.fs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ module TaskResult =
option
|> Task.map (Result.requireSome error)

let inline requireSomeWith ifErrorThunk option =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Doc comments

option
|> Task.map (Result.requireSomeWith ifErrorThunk)

// Converts an task-wrapped Option to a Result, using the given error if Some.
let inline requireNone error option =
option
Expand Down
16 changes: 16 additions & 0 deletions tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,22 @@ let requireSomeTests =
|> Expect.hasJobErrorValueSync err
]

[<Tests>]
let requireSomeWithTests =
testList "JobResult.requireSomeWith Tests" [
testCase "requireSomeWith happy path"
<| fun _ ->
toJob (Some 42)
|> JobResult.requireSomeWith (fun () -> err)
|> Expect.hasJobOkValueSync 42

testCase "requireSomeWith error path"
<| fun _ ->
toJob None
|> JobResult.requireSomeWith (fun () -> err)
|> Expect.hasJobErrorValueSync err
]

[<Tests>]
let requireNoneTests =
testList "JobResult.requireNone Tests" [
Expand Down
16 changes: 16 additions & 0 deletions tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskResult.fs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,22 @@ let requireSomeTests =
|> Expect.hasTaskErrorValueSync err
]

[<Tests>]
let requireSomeWithTests =
testList "TaskResult.requireSomeWith Tests" [
testCase "requireSomeWith happy path"
<| fun _ ->
toTask (Some 42)
|> TaskResult.requireSomeWith (fun () -> err)
|> Expect.hasTaskOkValueSync 42

testCase "requireSomeWith error path"
<| fun _ ->
toTask None
|> TaskResult.requireSomeWith (fun () -> err)
|> Expect.hasTaskErrorValueSync err
]

[<Tests>]
let requireNoneTests =
testList "TaskResult.requireNone Tests" [
Expand Down
13 changes: 13 additions & 0 deletions tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,18 @@ let requireSomeTests =
|> Expect.hasAsyncErrorValue err)
]

let requireSomeWithTests =
testList "AsyncResult.requireSomeWith Tests" [
testCaseAsync "requireSomeWith happy path"
<| (toAsync (Some 42)
|> AsyncResult.requireSomeWith (fun () -> err)
|> Expect.hasAsyncOkValue 42)

testCaseAsync "requireSomeWith error path"
<| (toAsync None
|> AsyncResult.requireSomeWith (fun () -> err)
|> Expect.hasAsyncErrorValue err)
]

let requireNoneTests =
testList "AsyncResult.requireNone Tests" [
Expand Down Expand Up @@ -1006,6 +1018,7 @@ let allTests =
requireTrueTests
requireFalseTests
requireSomeTests
requireSomeWithTests
requireNoneTests
requireValueSomeTests
requireValueNoneTests
Expand Down
14 changes: 14 additions & 0 deletions tests/FsToolkit.ErrorHandling.Tests/Result.fs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,19 @@ let requireSomeTests =
|> Expect.hasErrorValue err
]

let requireSomeWithTests =
testList "requireSomeWith Tests" [
testCase "requireSomeWith happy path"
<| fun _ ->
Result.requireSomeWith (fun () -> err) (Some 42)
|> Expect.hasOkValue 42

testCase "requireSomeWith error path"
<| fun _ ->
Result.requireSomeWith (fun () -> err) None
|> Expect.hasErrorValue err
]

let requireNotNullTests =
testList "requireNotNull Tests" [
testCase "requireNotNull happy path"
Expand Down Expand Up @@ -914,6 +927,7 @@ let allTests =
requireTrueTests
requireFalseTests
requireSomeTests
requireSomeWithTests
requireNoneTests
requireValueSomeTests
requireValueNoneTests
Expand Down
Loading