diff --git a/gitbook/result/requireFunctions.md b/gitbook/result/requireFunctions.md index 31b152dd..a829fb03 100644 --- a/gitbook/result/requireFunctions.md +++ b/gitbook/result/requireFunctions.md @@ -66,7 +66,7 @@ let result : Result = ## 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 @@ -96,6 +96,38 @@ let result : Result = // 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 = + Some 1 + |> Result.requireSomeWith (fun () -> "Value must be Some") + +// Ok () +``` + +#### Example 2 + +```fsharp +let result : Result = + 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. diff --git a/src/FsToolkit.ErrorHandling.JobResult/JobResult.fs b/src/FsToolkit.ErrorHandling.JobResult/JobResult.fs index 63b8c4e6..b97f2410 100644 --- a/src/FsToolkit.ErrorHandling.JobResult/JobResult.fs +++ b/src/FsToolkit.ErrorHandling.JobResult/JobResult.fs @@ -1,4 +1,4 @@ -namespace FsToolkit.ErrorHandling +namespace FsToolkit.ErrorHandling open Hopac open Hopac.Infixes @@ -124,6 +124,10 @@ module JobResult = option |> Job.map (Result.requireSome error) + let inline requireSomeWith ifErrorThunk option = + option + |> 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 diff --git a/src/FsToolkit.ErrorHandling/AsyncResult.fs b/src/FsToolkit.ErrorHandling/AsyncResult.fs index 0335121e..ba7bdbc6 100644 --- a/src/FsToolkit.ErrorHandling/AsyncResult.fs +++ b/src/FsToolkit.ErrorHandling/AsyncResult.fs @@ -157,6 +157,13 @@ module AsyncResult = value |> Async.map (Result.requireSome error) + let inline requireSomeWith + (ifErrorThunk: unit -> 'error) + (value: Async<'ok option>) + : Async> = + 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) diff --git a/src/FsToolkit.ErrorHandling/Result.fs b/src/FsToolkit.ErrorHandling/Result.fs index fc2f6261..52316375 100644 --- a/src/FsToolkit.ErrorHandling/Result.fs +++ b/src/FsToolkit.ErrorHandling/Result.fs @@ -307,6 +307,22 @@ module Result = | Some x -> Ok x | None -> Error error + /// + /// Returns the contained value if Some, otherwise evaluates and returns the value. + /// + /// Documentation is found here: https://demystifyfp.gitbook.io/fstoolkit-errorhandling/fstoolkit.errorhandling/result/others#requireSomeWith + /// + /// The function to evaluate if the result is None. + /// The input option. + /// The contained value if Some, otherwise the result of evaluating . + let inline requireSomeWith + (ifErrorThunk: unit -> 'error) + (option: 'ok option) + : Result<'ok, 'error> = + match option with + | Some x -> Ok x + | None -> Error(ifErrorThunk ()) + /// /// Requires a value to be None, otherwise returns an error result. /// diff --git a/src/FsToolkit.ErrorHandling/TaskResult.fs b/src/FsToolkit.ErrorHandling/TaskResult.fs index 8abfa50c..f3c93bf5 100644 --- a/src/FsToolkit.ErrorHandling/TaskResult.fs +++ b/src/FsToolkit.ErrorHandling/TaskResult.fs @@ -109,6 +109,10 @@ module TaskResult = option |> Task.map (Result.requireSome error) + let inline requireSomeWith ifErrorThunk option = + 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 diff --git a/tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs b/tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs index 793d49d4..8c5fed21 100644 --- a/tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs +++ b/tests/FsToolkit.ErrorHandling.JobResult.Tests/JobResult.fs @@ -284,6 +284,22 @@ let requireSomeTests = |> Expect.hasJobErrorValueSync err ] +[] +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 + ] + [] let requireNoneTests = testList "JobResult.requireNone Tests" [ diff --git a/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskResult.fs b/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskResult.fs index ae36e625..e7e4975d 100644 --- a/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskResult.fs +++ b/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskResult.fs @@ -289,6 +289,22 @@ let requireSomeTests = |> Expect.hasTaskErrorValueSync err ] +[] +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 + ] + [] let requireNoneTests = testList "TaskResult.requireNone Tests" [ diff --git a/tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs b/tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs index be85a5e2..73e4ebd4 100644 --- a/tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs +++ b/tests/FsToolkit.ErrorHandling.Tests/AsyncResult.fs @@ -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" [ @@ -1006,6 +1018,7 @@ let allTests = requireTrueTests requireFalseTests requireSomeTests + requireSomeWithTests requireNoneTests requireValueSomeTests requireValueNoneTests diff --git a/tests/FsToolkit.ErrorHandling.Tests/Result.fs b/tests/FsToolkit.ErrorHandling.Tests/Result.fs index acec025c..4fd4414f 100644 --- a/tests/FsToolkit.ErrorHandling.Tests/Result.fs +++ b/tests/FsToolkit.ErrorHandling.Tests/Result.fs @@ -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" @@ -914,6 +927,7 @@ let allTests = requireTrueTests requireFalseTests requireSomeTests + requireSomeWithTests requireNoneTests requireValueSomeTests requireValueNoneTests