From dc62ac85e3f311f6d72eca70d2278a462e78a3f3 Mon Sep 17 00:00:00 2001 From: sheridanchris Date: Thu, 23 Nov 2023 20:41:45 -0600 Subject: [PATCH 1/2] Add Task/AsyncOption defaultValue and defaultWith --- .../TaskOption.fs | 11 +++++ src/FsToolkit.ErrorHandling/AsyncOption.fs | 11 +++++ .../TaskOption.fs | 48 +++++++++++++++++++ .../AsyncOption.fs | 44 +++++++++++++++++ 4 files changed, 114 insertions(+) diff --git a/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs b/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs index 4bafc5c6..50ccec5c 100644 --- a/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs +++ b/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs @@ -53,3 +53,14 @@ module TaskOption = | Some v -> onSome v | None -> onNone () ) + + let inline defaultValue (value: 'value) (taskOption: Task<'value option>) = + taskOption + |> Task.map (Option.defaultValue value) + + let inline defaultWith + ([] defThunk: unit -> 'value) + (taskOption: Task<'value option>) + : Task<'value> = + taskOption + |> Task.map (Option.defaultWith defThunk) diff --git a/src/FsToolkit.ErrorHandling/AsyncOption.fs b/src/FsToolkit.ErrorHandling/AsyncOption.fs index 14a996a8..b55cf03c 100644 --- a/src/FsToolkit.ErrorHandling/AsyncOption.fs +++ b/src/FsToolkit.ErrorHandling/AsyncOption.fs @@ -52,3 +52,14 @@ module AsyncOption = | Some v -> onSome v | None -> onNone ) + + let inline defaultValue (value: 'value) (asyncOption: Async<'value option>) = + asyncOption + |> Async.map (Option.defaultValue value) + + let inline defaultWith + ([] defThunk: unit -> 'value) + (asyncOption: Async<'value option>) + : Async<'value> = + asyncOption + |> Async.map (Option.defaultWith defThunk) diff --git a/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskOption.fs b/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskOption.fs index cfef49d1..36cae0e1 100644 --- a/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskOption.fs +++ b/tests/FsToolkit.ErrorHandling.TaskResult.Tests/TaskOption.fs @@ -154,6 +154,52 @@ let eitherTests = } ] +let defaultValueTests = + testList "TaskOption.defaultValue Tests" [ + testCaseTask "Some" + <| fun () -> + task { + let defaultValue = 10 + let expectedValue = 5 + + let taskOption = TaskOption.retn expectedValue + let! result = TaskOption.defaultValue defaultValue taskOption + Expect.equal result expectedValue "" + } + + testCaseTask "None" + <| fun () -> + task { + let expectedValue = 10 + let taskOption = Task.singleton None + let! result = TaskOption.defaultValue expectedValue taskOption + Expect.equal result expectedValue "" + } + ] + +let defaultWithTests = + testList "TaskOption.defaultWith Tests" [ + testCaseTask "Some" + <| fun () -> + task { + let defaultValue = 10 + let expectedValue = 5 + + let taskOption = TaskOption.retn expectedValue + let! result = TaskOption.defaultWith (fun () -> defaultValue) taskOption + Expect.equal result expectedValue "" + } + + testCaseTask "None" + <| fun () -> + task { + let expectedValue = 10 + let taskOption = Task.singleton None + let! result = TaskOption.defaultWith (fun () -> expectedValue) taskOption + Expect.equal result expectedValue "" + } + ] + let allTests = testList "Task Option Tests" [ mapTests @@ -162,4 +208,6 @@ let allTests = retnTests taskOptionOperatorTests eitherTests + defaultValueTests + defaultWithTests ] diff --git a/tests/FsToolkit.ErrorHandling.Tests/AsyncOption.fs b/tests/FsToolkit.ErrorHandling.Tests/AsyncOption.fs index a3b45708..41274465 100644 --- a/tests/FsToolkit.ErrorHandling.Tests/AsyncOption.fs +++ b/tests/FsToolkit.ErrorHandling.Tests/AsyncOption.fs @@ -127,6 +127,48 @@ let eitherTests = } ] +let defaultValueTests = + testList "TaskOption.defaultValue Tests" [ + testCaseAsync "Some" + <| async { + let defaultValue = 10 + let expectedValue = 5 + + let asyncOption = AsyncOption.retn expectedValue + let! result = AsyncOption.defaultValue defaultValue asyncOption + Expect.equal result expectedValue "" + } + + testCaseAsync "None" + <| async { + let expectedValue = 10 + let asyncOption = Async.singleton None + let! result = AsyncOption.defaultValue expectedValue asyncOption + Expect.equal result expectedValue "" + } + ] + +let defaultWithTests = + testList "AsyncOption.defaultWith Tests" [ + testCaseAsync "Some" + <| async { + let defaultValue = 10 + let expectedValue = 5 + + let asyncOption = AsyncOption.retn expectedValue + let! result = AsyncOption.defaultWith (fun () -> defaultValue) asyncOption + Expect.equal result expectedValue "" + } + + testCaseAsync "None" + <| async { + let expectedValue = 10 + let asyncOption = Async.singleton None + let! result = AsyncOption.defaultWith (fun () -> expectedValue) asyncOption + Expect.equal result expectedValue "" + } + ] + let allTests = testList "Async Option Tests" [ mapTests @@ -135,4 +177,6 @@ let allTests = retnTests asyncOptionOperatorTests eitherTests + defaultValueTests + defaultWithTests ] From cca2aab2882e0f0b35a8a4d399e1f5e7909fad1a Mon Sep 17 00:00:00 2001 From: sheridanchris Date: Fri, 24 Nov 2023 13:16:06 -0600 Subject: [PATCH 2/2] Add doc comments --- .../TaskOption.fs | 16 ++++++++++++++++ src/FsToolkit.ErrorHandling/AsyncOption.fs | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs b/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs index 50ccec5c..a154a71c 100644 --- a/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs +++ b/src/FsToolkit.ErrorHandling.TaskResult/TaskOption.fs @@ -54,10 +54,26 @@ module TaskOption = | None -> onNone () ) + /// + /// Gets the value of the option if the option is Some, otherwise returns the specified default value. + /// + /// The specified default value. + /// The input option. + /// + /// The option if the option is Some, else the default value. + /// let inline defaultValue (value: 'value) (taskOption: Task<'value option>) = taskOption |> Task.map (Option.defaultValue value) + /// + /// Gets the value of the option if the option is Some, otherwise evaluates and returns the result. + /// + /// A thunk that provides a default value when evaluated. + /// The input option. + /// + /// The option if the option is Some, else the result of evaluating . + /// let inline defaultWith ([] defThunk: unit -> 'value) (taskOption: Task<'value option>) diff --git a/src/FsToolkit.ErrorHandling/AsyncOption.fs b/src/FsToolkit.ErrorHandling/AsyncOption.fs index b55cf03c..400adae6 100644 --- a/src/FsToolkit.ErrorHandling/AsyncOption.fs +++ b/src/FsToolkit.ErrorHandling/AsyncOption.fs @@ -53,10 +53,26 @@ module AsyncOption = | None -> onNone ) + /// + /// Gets the value of the option if the option is Some, otherwise returns the specified default value. + /// + /// The specified default value. + /// The input option. + /// + /// The option if the option is Some, else the default value. + /// let inline defaultValue (value: 'value) (asyncOption: Async<'value option>) = asyncOption |> Async.map (Option.defaultValue value) + /// + /// Gets the value of the option if the option is Some, otherwise evaluates and returns the result. + /// + /// A thunk that provides a default value when evaluated. + /// The input option. + /// + /// The option if the option is Some, else the result of evaluating . + /// let inline defaultWith ([] defThunk: unit -> 'value) (asyncOption: Async<'value option>)