Skip to content

Commit 3163462

Browse files
bartelinkTheAngryByrd
authored andcommitted
feat(Seq)!: Add sequenceResultA, align sequenceResultM (#255)
* Roll on '24 * refactor(Seq.sequenceResultM)!: Change Ok to Array * docs: sequenceResultM * feat(Seq): sequenceResultA * f sequenceResultM docs * Supress compile error * Fix proposed version
1 parent 0a5fbf0 commit 3163462

File tree

8 files changed

+109
-518
lines changed

8 files changed

+109
-518
lines changed

RELEASE_NOTES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2+
### 5.0.0-alpha.1
3+
- [refactor!: Seq.sequenceResultM returns Array instead of seq](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/255) [@bartelink](https://github.com/bartelink)
4+
- [feat(Seq): sequenceResultA](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/255) [@bartelink](https://github.com/bartelink)
5+
16
### 4.18.0 - October 23, 2024
27
- [Add Array errorhandling](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/279) Credits @DashieTM
38

build/build.fsproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
<OutputType>Exe</OutputType>
55
<TargetFramework>net7.0</TargetFramework>
66
<IsPackable>false</IsPackable>
7+
<!-- <NoWarn>NU1904</NoWarn>-->
8+
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
79
</PropertyGroup>
810
<ItemGroup>
911
<Compile Include="DotEnv.fs" />
1012
<Compile Include="build.fs" />
1113
</ItemGroup>
1214
<Import Project="..\.paket\Paket.Restore.targets" />
13-
</Project>
15+
</Project>

gitbook/list/sequenceResultA.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let checkIfAllPrime (numbers : int list) =
5959
numbers
6060
|> List.map isPrime // Result<bool, string> list
6161
|> List.sequenceResultA // Result<bool list, string list>
62-
|> Result.map (List.forall id) // shortened version of '|> Result.map (fun boolList -> boolList |> List.map (fun x -> x = true))'
62+
|> Result.map (List.forall id) // shortened version of '|> Result.map (fun boolList -> boolList |> List.forall (fun x -> x = true))
6363
6464
let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
6565
// Error ["1 must be greater than 1"]

gitbook/seq/sequenceResultA.md

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ Namespace: `FsToolkit.ErrorHandling`
55
## Function Signature
66

77
```fsharp
8-
Result<'a, 'b> seq -> Result<'a seq, 'b seq>
8+
seq<Result<'a, 'b>> -> Result<'a[], 'b[]>
99
```
1010

11-
Note that `sequence` is the same as `traverse id`. See also [Seq.traverseResultA](traverseResultA.md).
12-
1311
This is applicative, collecting all errors. Compare the example below with [sequenceResultM](sequenceResultM.md).
1412

1513
See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpforfunandprofit.com/posts/elevated-world-4/).
@@ -23,53 +21,49 @@ See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpfo
2321
let tryParseInt str =
2422
match Int32.TryParse str with
2523
| true, x -> Ok x
26-
| false, _ ->
27-
Error (sprintf "unable to parse '%s' to integer" str)
24+
| false, _ -> Error $"unable to parse '{str}' to integer"
2825
2926
["1"; "2"; "3"]
3027
|> Seq.map tryParseInt
3128
|> Seq.sequenceResultA
32-
// Ok [1; 2; 3]
29+
// Ok [| 1; 2; 3 |]
3330
3431
["1"; "foo"; "3"; "bar"]
3532
|> Seq.map tryParseInt
3633
|> Seq.sequenceResultA
37-
// Error ["unable to parse 'foo' to integer";
38-
// "unable to parse 'bar' to integer"]
34+
// Error [| "unable to parse 'foo' to integer"
35+
// "unable to parse 'bar' to integer" |]
3936
```
4037

4138
### Example 2
4239

4340
```fsharp
4441
// int -> Result<bool, string>
45-
let isPrime (x : int) =
46-
if x < 2 then
47-
sprintf "%i must be greater than 1" x |> Error
48-
elif
49-
x = 2 then Ok true
42+
let isPrime (x: int) =
43+
if x < 2 then Error $"{x} must be greater than 1"
44+
elif x = 2 then Ok true
5045
else
5146
let rec isPrime' (x : int) (i : int) =
5247
if i * i > x then Ok true
5348
elif x % i = 0 then Ok false
5449
else isPrime' x (i + 1)
5550
isPrime' x 2
5651
57-
// int seq -> Result<bool, string seq>
58-
let checkIfAllPrime (numbers : int seq) =
59-
numbers
60-
|> Seq.map isPrime // Result<bool, string> seq
61-
|> Seq.sequenceResultA // Result<bool seq, string seq>
62-
|> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun boolSeq -> boolSeq |> Seq.map (fun x -> x = true))'
52+
// seq<int> -> Result<bool, string[]>
53+
let checkIfAllPrime (numbers: seq<int>) =
54+
seq { for x in numbers -> isPrime x } // Result<bool, string> seq
55+
|> Seq.sequenceResultA // Result<bool[], string[]>
56+
|> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun results -> results |> Array.forall (fun x -> x = true))'
6357
64-
let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
65-
// Error ["1 must be greater than 1"]
58+
let a = [| 1; 2; 3; 4; 5 |] |> checkIfAllPrime
59+
// Error [| "1 must be greater than 1" |]
6660
67-
let b = [1; 2; 3; 4; 5; 0;] |> checkIfAllPrime
68-
// Error ["1 must be greater than 1"; "0 must be greater than 1"]
61+
let b = [ 1; 2; 3; 4; 5; 0 ] |> checkIfAllPrime
62+
// Error [| "1 must be greater than 1"; "0 must be greater than 1" |]
6963
70-
let a = [2; 3; 4; 5;] |> checkIfAllPrime
64+
let a = seq { 2; 3; 4; 5 } |> checkIfAllPrime
7165
// Ok false
7266
73-
let a = [2; 3; 5;] |> checkIfAllPrime
67+
let a = seq { 2; 3; 5 } |> checkIfAllPrime
7468
// Ok true
7569
```

gitbook/seq/sequenceResultM.md

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ Namespace: `FsToolkit.ErrorHandling`
55
## Function Signature
66

77
```fsharp
8-
Result<'a, 'b> seq -> Result<'a seq, 'b>
8+
seq<Result<'a, 'b>> -> Result<'a[], 'b>
99
```
1010

11-
Note that `sequence` is the same as `traverse id`. See also [Seq.traverseResultM](traverseResultM.md).
12-
1311
This is monadic, stopping on the first error. Compare the example below with [sequenceResultA](sequenceResultA.md).
1412

1513
See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpforfunandprofit.com/posts/elevated-world-4/).
@@ -23,15 +21,14 @@ See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpfo
2321
let tryParseInt str =
2422
match Int32.TryParse str with
2523
| true, x -> Ok x
26-
| false, _ ->
27-
Error (sprintf "unable to parse '%s' to integer" str)
24+
| false, _ -> Error $"unable to parse '{str}' to integer"
2825
2926
["1"; "2"; "3"]
3027
|> Seq.map tryParseInt
3128
|> Seq.sequenceResultM
32-
// Ok [1; 2; 3]
29+
// Ok [| 1; 2; 3 |]
3330
34-
["1"; "foo"; "3"; "bar"]
31+
seq { "1"; "foo"; "3"; "bar" }
3532
|> Seq.map tryParseInt
3633
|> Seq.sequenceResultM
3734
// Error "unable to parse 'foo' to integer"
@@ -41,32 +38,30 @@ let tryParseInt str =
4138

4239
```fsharp
4340
// int -> Result<bool, string>
44-
let isPrime (x : int) =
45-
if x < 2 then
46-
sprintf "%i must be greater than 1" x |> Error
47-
elif
48-
x = 2 then Ok true
41+
let isPrime (x: int) =
42+
if x < 2 then Error $"{x} must be greater than 1"
43+
elif x = 2 then Ok true
4944
else
5045
let rec isPrime' (x : int) (i : int) =
5146
if i * i > x then Ok true
5247
elif x % i = 0 then Ok false
5348
else isPrime' x (i + 1)
5449
isPrime' x 2
5550
56-
// int seq -> Result<bool, string seq>
57-
let checkIfAllPrime (numbers : int seq) =
51+
// int seq -> Result<bool, string[]>
52+
let checkIfAllPrime (numbers: seq<int>) =
5853
numbers
59-
|> Seq.map isPrime // Result<bool, string> seq
60-
|> Seq.sequenceResultM // Result<bool seq, string>
61-
|> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun boolSeq -> boolSeq |> Seq.map (fun x -> x = true))';
54+
|> Seq.map isPrime // seq<Result<bool, string>>
55+
|> Seq.sequenceResultM // Result<bool[], string>
56+
|> Result.map (Array.forall id) // shortened version of '|> Result.map (fun bools -> bools |> Array.forall (fun x -> x = true))'
6257
63-
let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
64-
// Error ["1 must be greater than 1"]
58+
let a = [ 1; 2; 3; 4; 5 ] |> checkIfAllPrime
59+
// Error [| "1 must be greater than 1" |]
6560
66-
let b = [1; 2; 3; 4; 5; 0;] |> checkIfAllPrime
67-
// Error ["1 must be greater than 1"]
61+
let b = [| 1; 2; 3; 4; 5; 0 |] |> checkIfAllPrime
62+
// Error [| "1 must be greater than 1" |]
6863
69-
let a = [2; 3; 4; 5;] |> checkIfAllPrime
64+
let a = seq { 2; 3; 4; 5 } |> checkIfAllPrime
7065
// Ok false
7166
7267
let a = [2; 3; 5;] |> checkIfAllPrime

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<PropertyGroup>
55
<Description>FsToolkit.ErrorHandling is an extensive utility library based around the F# Result type, enabling consistent and powerful error handling.</Description>
66
<Authors>demystifyfp, TheAngryByrd</Authors>
7-
<Copyright>Copyright © 2018-23</Copyright>
7+
<Copyright>Copyright © 2018-24</Copyright>
88
<PackageProjectUrl>https://demystifyfp.gitbook.io/fstoolkit-errorhandling</PackageProjectUrl>
99
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1010
<PackageReadmeFile>README.md</PackageReadmeFile> <!--https://docs.microsoft.com/en-gb/nuget/reference/msbuild-targets#packagereadmefile -->

src/FsToolkit.ErrorHandling/Seq.fs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
namespace FsToolkit.ErrorHandling
2-
31
[<RequireQualifiedAccess>]
4-
module Seq =
2+
module FsToolkit.ErrorHandling.Seq
53

64
/// <summary>
75
/// Applies a function to each element of a sequence and returns a single result

0 commit comments

Comments
 (0)