Skip to content
Merged
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
9 changes: 9 additions & 0 deletions gitbook/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@
* [map](taskOption/map.md)
* [Other Functions](taskOption/others.md)
* [zip](taskOption/zip.md)

* TaskValueOption
* [apply](taskValueOption/apply.md)
* [bind](taskValueOption/bind.md)
* [Computation Expression](taskValueOption/ce.md)
* [either](taskValueOption/either.md)
* [map](taskValueOption/map.md)
* [Other Functions](taskValueOption/others.md)
* [zip](taskValueOption/zip.md)

* TaskResult
* [apply](taskResult/apply.md)
Expand Down
48 changes: 48 additions & 0 deletions gitbook/taskValueOption/apply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# TaskValueOption.apply

Namespace: `FsToolkit.ErrorHandling`

Function Signature:

```fsharp
Task<('a -> 'b) voption> -> Task<'a voption> -> Task<'b voption>
```

## Examples

Take the following function for example

```fsharp
// string -> int
let characterCount (s: string) = s.Length
```

### Example 1

```fsharp
let result =
TaskValueOption.valueSome "foo" // Task<string voption>
|> TaskValueOption.apply (TaskValueOption.valueSome characterCount) // Task<int voption>

// task { ValueSome 3 }
```

### Example 2

```fsharp
let result =
Task.singleton ValueNone // Task<string voption>
|> TaskValueOption.apply (TaskValueOption.valueSome characterCount) // Task<int voption>

// task { ValueNone }
```

### Example 3

```fsharp
let result : Task<int voption> =
TaskValueOption.valueSome "foo" // Task<string voption>
|> TaskValueOption.apply (Task.singleton ValueNone) // Task<int voption>

// task { ValueNone }
```
68 changes: 68 additions & 0 deletions gitbook/taskValueOption/bind.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# TaskValueOption.bind

Namespace: `FsToolkit.ErrorHandling`

## Function Signature

```fsharp
('input -> Task<'output voption>) -> Task<'input voption> -> Task<'output voption>
```

## Examples

Take the following function for example

```fsharp
type Account =
{ EmailAddress : string
Name : string }

// string -> Task<Account voption>
let lookupAccountByEmail email = task {
let john = { EmailAddress = "[email protected]"; Name = "John Johnson" }
let jeff = { EmailAddress = "[email protected]"; Name = "Jeff Jefferson" }
let jack = { EmailAddress = "[email protected]"; Name = "Jack Jackson" }

// Just a map lookup, but imagine we look up an account in our database
let accounts = Map.ofList [
("[email protected]", john)
("[email protected]", jeff)
("[email protected]", jack)
]

return
accounts
|> Map.tryFind email
|> Option.toValueOption
}
```

### Example 1

```fsharp
let taskOpt : Task<Account voption> =
TaskValueOption.valueSome "[email protected]" // Task<string voption>
|> TaskValueOption.bind lookupAccountByEmail // Task<Account voption>

// task { ValueSome { EmailAddress = "[email protected]"; Name = "John Johnson" } }
```

### Example 2

```fsharp
let taskVOpt : Task<Account voption> =
TaskValueOption.some "[email protected]" // Task<string voption>
|> TaskValueOption.bind lookupAccountByEmail // Task<Account voption>

// task { ValueNone }
```

### Example 3

```fsharp
let taskVOpt : Task<Account voption> =
Task.singleton ValueNone // Task<string voption>
|> TaskValueOption.bind lookupAccountByEmail // Task<Account voption>

// task { ValueNone }
```
26 changes: 26 additions & 0 deletions gitbook/taskValueOption/ce.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## TaskValueOption Computation Expression

Namespace: `FsToolkit.ErrorHandling`

## Examples:

### Example 1

Given a personId and an age, find a person and update their age.

```fsharp
tryParseInt : string -> int voption
tryFindPersonById : int -> Task<Person voption>
updatePerson : Person -> Task<unit>
```

```fsharp
// Task<unit voption>
let addResult = taskValueOption {
let! personId = tryParseInt "3001"
let! age = tryParseInt "35"
let! person = tryFindPersonById personId
let person = { person with Age = age }
do! updatePerson person
}
```
33 changes: 33 additions & 0 deletions gitbook/taskValueOption/either.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# TaskValueOption.either

Namespace: `FsToolkit.ErrorHandling`

## Function Signature

Provide two functions to execute depending on the value of the voption. If the voption is `ValueSome`, the first function will be executed. If the voption is `ValueNone`, the second function will be executed.

```fsharp
(onValueSome : 'T -> Task<'output>)
-> (onValueNone : Task<'output>)
-> (input : Task<'T voption>)
-> Task<'output>
```

## Examples

### Example 1

```fsharp
TaskValueOption.either (fun x -> task { x * 2 }) (task { 0 }) (TaskValueOption.valueSome 5)

// task { 10 }
```

### Example 2

```fsharp
TaskValueOption.either (fun x -> task { x * 2 }) (task { 0 }) ValueNone

// task { 0 }
```

30 changes: 30 additions & 0 deletions gitbook/taskValueOption/map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# TaskValueOption.map

Namespace: `FsToolkit.ErrorHandling`

Apply a function to the value of a task voption if it is `ValueSome`. If the option is `ValueNone`, return `ValueNone`.

## Function Signature

```fsharp
('input -> 'output) -> Task<'input voption> -> Task<'output voption>
```

## Examples

### Example 1

```fsharp
TaskValueOption.map (fun x -> x + 1) (TaskValueOption.valueSome 1)

// task { ValueSome 2 }
```

### Example 2

```fsharp
TaskValueOption.map (fun x -> x + 1) (Task.singleton ValueNone)

// task { ValueNone }
```

33 changes: 33 additions & 0 deletions gitbook/taskValueOption/others.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Other TaskValueOption Functions

## defaultValue

Returns the contained value if ValueSome, otherwise returns the provided value

### Function Signature

```fsharp
'a -> Task<'a voption> -> Task<'a>
```

## defaultWith

Returns the contained value if ValueSome, otherwise evaluates the given function and returns the result.

### Function Signature

```fsharp
(unit -> 'a) -> Task<'a voption> -> Task<'a>
```

## valueSome

Wraps the provided value in an Task<'a voption>

### Function Signature

```fsharp
'a -> Task<'a voption>
```


33 changes: 33 additions & 0 deletions gitbook/taskValueOption/zip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# TaskValueOption.zip

Namespace: `FsToolkit.ErrorHandling`

Takes two voptions and returns a tuple of the pair or ValueNone if either are ValueNone

## Function Signature

```fsharp
Task<'left voption> -> Task<'right voption> -> Task<('left * 'right) voption>
```

## Examples

### Example 1

```fsharp
let left = TaskValueOption.valueSome 123
let right = TaskValueOption.valueSome "abc"

TaskValueOption.zip left right
// task { ValueSome (123, "abc") }
```

### Example 2

```fsharp
let left = TaskValueOption.valueSome 123
let right = Task.singleton ValueNone

TaskValueOption.zip left right
// task { ValueNone }
```
3 changes: 3 additions & 0 deletions src/FsToolkit.ErrorHandling/FsToolkit.ErrorHandling.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@
<Compile Include="AsyncOptionCE.fs" />
<Compile Include="AsyncOptionOp.fs" />
<Compile Include="TaskOption.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="TaskValueOption.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="TaskOptionCE.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="TaskValueOptionCE.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="TaskOptionOp.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="TaskValueOptionOp.fs" Condition="'$(FABLE_COMPILER)' != 'true'" />
<Compile Include="AsyncResultOption.fs" />
<Compile Include="AsyncResultOptionCE.fs" />
<Compile Include="AsyncResultOptionOp.fs" />
Expand Down
79 changes: 79 additions & 0 deletions src/FsToolkit.ErrorHandling/TaskValueOption.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
namespace FsToolkit.ErrorHandling

open System.Threading.Tasks


[<RequireQualifiedAccess>]
module TaskValueOption =

let inline map ([<InlineIfLambda>] f) ar = Task.map (ValueOption.map f) ar

let inline bind ([<InlineIfLambda>] f) (ar: Task<_>) =
task {
let! opt = ar

let t =
match opt with
| ValueSome x -> f x
| ValueNone -> task { return ValueNone }

return! t
}

let inline valueSome x = task { return ValueSome x }

let inline apply f x =
bind (fun f' -> bind (fun x' -> valueSome (f' x')) x) f

let inline zip x1 x2 =
Task.zip x1 x2
|> Task.map (fun (r1, r2) -> ValueOption.zip r1 r2)


/// <summary>
/// Returns result of running <paramref name="onValueSome"/> if it is <c>ValueSome</c>, otherwise returns result of running <paramref name="onValueNone"/>
/// </summary>
/// <param name="onValueSome">The function to run if <paramref name="input"/> is <c>ValueSome</c></param>
/// <param name="onValueNone">The function to run if <paramref name="input"/> is <c>ValueNone</c></param>
/// <param name="input">The input voption.</param>
/// <returns>
/// The result of running <paramref name="onValueSome"/> if the input is <c>ValueSome</c>, else returns result of running <paramref name="onValueNone"/>.
/// </returns>
let inline either
([<InlineIfLambda>] onValueSome: 'input -> Task<'output>)
([<InlineIfLambda>] onValueNone: unit -> Task<'output>)
(input: Task<'input voption>)
: Task<'output> =
input
|> Task.bind (
function
| ValueSome v -> onValueSome v
| ValueNone -> onValueNone ()
)

/// <summary>
/// Gets the value of the option if the option is <c>Some</c>, otherwise returns the specified default value.
/// </summary>
/// <param name="value">The specified default value.</param>
/// <param name="taskValueOption">The input option.</param>
/// <returns>
/// The option if the option is <c>Some</c>, else the default value.
/// </returns>
let inline defaultValue (value: 'value) (taskValueOption: Task<'value voption>) =
taskValueOption
|> Task.map (ValueOption.defaultValue value)

/// <summary>
/// Gets the value of the voption if the voption is <c>ValueSome</c>, otherwise evaluates <paramref name="defThunk"/> and returns the result.
/// </summary>
/// <param name="defThunk">A thunk that provides a default value when evaluated.</param>
/// <param name="taskValueOption">The input voption.</param>
/// <returns>
/// The voption if the option is <c>ValueSome</c>, else the result of evaluating <paramref name="defThunk"/>.
/// </returns>
let inline defaultWith
([<InlineIfLambda>] defThunk: unit -> 'value)
(taskValueOption: Task<'value voption>)
: Task<'value> =
taskValueOption
|> Task.map (ValueOption.defaultWith defThunk)
Loading
Loading