diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7b5e990e..4cc5917f 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,3 +1,8 @@
+
+### 5.0.0-alpha.1
+- [refactor!: Seq.sequenceResultM returns Array instead of seq](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/255) [@bartelink](https://github.com/bartelink)
+- [feat(Seq): sequenceResultA](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/255) [@bartelink](https://github.com/bartelink)
+
### 4.18.0 - October 23, 2024
- [Add Array errorhandling](https://github.com/demystifyfp/FsToolkit.ErrorHandling/pull/279) Credits @DashieTM
diff --git a/build/build.fsproj b/build/build.fsproj
index 8a227d7a..e05d688c 100644
--- a/build/build.fsproj
+++ b/build/build.fsproj
@@ -4,10 +4,12 @@
Exe
net7.0
false
+
+ false
-
\ No newline at end of file
+
diff --git a/gitbook/list/sequenceResultA.md b/gitbook/list/sequenceResultA.md
index a2e0dacc..f904d42b 100644
--- a/gitbook/list/sequenceResultA.md
+++ b/gitbook/list/sequenceResultA.md
@@ -59,7 +59,7 @@ let checkIfAllPrime (numbers : int list) =
numbers
|> List.map isPrime // Result list
|> List.sequenceResultA // Result
- |> Result.map (List.forall id) // shortened version of '|> Result.map (fun boolList -> boolList |> List.map (fun x -> x = true))'
+ |> Result.map (List.forall id) // shortened version of '|> Result.map (fun boolList -> boolList |> List.forall (fun x -> x = true))
let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
// Error ["1 must be greater than 1"]
diff --git a/gitbook/seq/sequenceResultA.md b/gitbook/seq/sequenceResultA.md
index 6364913a..60b6761b 100644
--- a/gitbook/seq/sequenceResultA.md
+++ b/gitbook/seq/sequenceResultA.md
@@ -5,11 +5,9 @@ Namespace: `FsToolkit.ErrorHandling`
## Function Signature
```fsharp
-Result<'a, 'b> seq -> Result<'a seq, 'b seq>
+seq> -> Result<'a[], 'b[]>
```
-Note that `sequence` is the same as `traverse id`. See also [Seq.traverseResultA](traverseResultA.md).
-
This is applicative, collecting all errors. Compare the example below with [sequenceResultM](sequenceResultM.md).
See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpforfunandprofit.com/posts/elevated-world-4/).
@@ -23,30 +21,27 @@ See also Scott Wlaschin's [Understanding traverse and sequence](https://fsharpfo
let tryParseInt str =
match Int32.TryParse str with
| true, x -> Ok x
- | false, _ ->
- Error (sprintf "unable to parse '%s' to integer" str)
+ | false, _ -> Error $"unable to parse '{str}' to integer"
["1"; "2"; "3"]
|> Seq.map tryParseInt
|> Seq.sequenceResultA
-// Ok [1; 2; 3]
+// Ok [| 1; 2; 3 |]
["1"; "foo"; "3"; "bar"]
|> Seq.map tryParseInt
|> Seq.sequenceResultA
-// Error ["unable to parse 'foo' to integer";
-// "unable to parse 'bar' to integer"]
+// Error [| "unable to parse 'foo' to integer"
+// "unable to parse 'bar' to integer" |]
```
### Example 2
```fsharp
// int -> Result
-let isPrime (x : int) =
- if x < 2 then
- sprintf "%i must be greater than 1" x |> Error
- elif
- x = 2 then Ok true
+let isPrime (x: int) =
+ if x < 2 then Error $"{x} must be greater than 1"
+ elif x = 2 then Ok true
else
let rec isPrime' (x : int) (i : int) =
if i * i > x then Ok true
@@ -54,22 +49,21 @@ let isPrime (x : int) =
else isPrime' x (i + 1)
isPrime' x 2
-// int seq -> Result
-let checkIfAllPrime (numbers : int seq) =
- numbers
- |> Seq.map isPrime // Result seq
- |> Seq.sequenceResultA // Result
- |> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun boolSeq -> boolSeq |> Seq.map (fun x -> x = true))'
+// seq -> Result
+let checkIfAllPrime (numbers: seq) =
+ seq { for x in numbers -> isPrime x } // Result seq
+ |> Seq.sequenceResultA // Result
+ |> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun results -> results |> Array.forall (fun x -> x = true))'
-let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
-// Error ["1 must be greater than 1"]
+let a = [| 1; 2; 3; 4; 5 |] |> checkIfAllPrime
+// Error [| "1 must be greater than 1" |]
-let b = [1; 2; 3; 4; 5; 0;] |> checkIfAllPrime
-// Error ["1 must be greater than 1"; "0 must be greater than 1"]
+let b = [ 1; 2; 3; 4; 5; 0 ] |> checkIfAllPrime
+// Error [| "1 must be greater than 1"; "0 must be greater than 1" |]
-let a = [2; 3; 4; 5;] |> checkIfAllPrime
+let a = seq { 2; 3; 4; 5 } |> checkIfAllPrime
// Ok false
-let a = [2; 3; 5;] |> checkIfAllPrime
+let a = seq { 2; 3; 5 } |> checkIfAllPrime
// Ok true
```
diff --git a/gitbook/seq/sequenceResultM.md b/gitbook/seq/sequenceResultM.md
index 4dddaa43..681bc0dd 100644
--- a/gitbook/seq/sequenceResultM.md
+++ b/gitbook/seq/sequenceResultM.md
@@ -5,11 +5,9 @@ Namespace: `FsToolkit.ErrorHandling`
## Function Signature
```fsharp
-Result<'a, 'b> seq -> Result<'a seq, 'b>
+seq> -> Result<'a[], 'b>
```
-Note that `sequence` is the same as `traverse id`. See also [Seq.traverseResultM](traverseResultM.md).
-
This is monadic, stopping on the first error. Compare the example below with [sequenceResultA](sequenceResultA.md).
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
let tryParseInt str =
match Int32.TryParse str with
| true, x -> Ok x
- | false, _ ->
- Error (sprintf "unable to parse '%s' to integer" str)
+ | false, _ -> Error $"unable to parse '{str}' to integer"
["1"; "2"; "3"]
|> Seq.map tryParseInt
|> Seq.sequenceResultM
-// Ok [1; 2; 3]
+// Ok [| 1; 2; 3 |]
-["1"; "foo"; "3"; "bar"]
+seq { "1"; "foo"; "3"; "bar" }
|> Seq.map tryParseInt
|> Seq.sequenceResultM
// Error "unable to parse 'foo' to integer"
@@ -41,11 +38,9 @@ let tryParseInt str =
```fsharp
// int -> Result
-let isPrime (x : int) =
- if x < 2 then
- sprintf "%i must be greater than 1" x |> Error
- elif
- x = 2 then Ok true
+let isPrime (x: int) =
+ if x < 2 then Error $"{x} must be greater than 1"
+ elif x = 2 then Ok true
else
let rec isPrime' (x : int) (i : int) =
if i * i > x then Ok true
@@ -53,20 +48,20 @@ let isPrime (x : int) =
else isPrime' x (i + 1)
isPrime' x 2
-// int seq -> Result
-let checkIfAllPrime (numbers : int seq) =
+// int seq -> Result
+let checkIfAllPrime (numbers: seq) =
numbers
- |> Seq.map isPrime // Result seq
- |> Seq.sequenceResultM // Result
- |> Result.map (Seq.forall id) // shortened version of '|> Result.map (fun boolSeq -> boolSeq |> Seq.map (fun x -> x = true))';
+ |> Seq.map isPrime // seq>
+ |> Seq.sequenceResultM // Result
+ |> Result.map (Array.forall id) // shortened version of '|> Result.map (fun bools -> bools |> Array.forall (fun x -> x = true))'
-let a = [1; 2; 3; 4; 5;] |> checkIfAllPrime
-// Error ["1 must be greater than 1"]
+let a = [ 1; 2; 3; 4; 5 ] |> checkIfAllPrime
+// Error [| "1 must be greater than 1" |]
-let b = [1; 2; 3; 4; 5; 0;] |> checkIfAllPrime
-// Error ["1 must be greater than 1"]
+let b = [| 1; 2; 3; 4; 5; 0 |] |> checkIfAllPrime
+// Error [| "1 must be greater than 1" |]
-let a = [2; 3; 4; 5;] |> checkIfAllPrime
+let a = seq { 2; 3; 4; 5 } |> checkIfAllPrime
// Ok false
let a = [2; 3; 5;] |> checkIfAllPrime
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index c4be768f..65508527 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -4,7 +4,7 @@
FsToolkit.ErrorHandling is an extensive utility library based around the F# Result type, enabling consistent and powerful error handling.
demystifyfp, TheAngryByrd
- Copyright © 2018-23
+ Copyright © 2018-24
https://demystifyfp.gitbook.io/fstoolkit-errorhandling
MIT
README.md
diff --git a/src/FsToolkit.ErrorHandling/Seq.fs b/src/FsToolkit.ErrorHandling/Seq.fs
index 89d47916..9cee77a4 100644
--- a/src/FsToolkit.ErrorHandling/Seq.fs
+++ b/src/FsToolkit.ErrorHandling/Seq.fs
@@ -1,7 +1,5 @@
-namespace FsToolkit.ErrorHandling
-
[]
-module Seq =
+module FsToolkit.ErrorHandling.Seq
///
/// Applies a function to each element of a sequence and returns a single result
diff --git a/tests/FsToolkit.ErrorHandling.Tests/Seq.fs b/tests/FsToolkit.ErrorHandling.Tests/Seq.fs
index 2059337d..516be12d 100644
--- a/tests/FsToolkit.ErrorHandling.Tests/Seq.fs
+++ b/tests/FsToolkit.ErrorHandling.Tests/Seq.fs
@@ -1,6 +1,5 @@
module SeqTests
-
#if FABLE_COMPILER_PYTHON
open Fable.Pyxpecto
#endif
@@ -10,6 +9,7 @@ open Fable.Mocha
#if !FABLE_COMPILER
open Expecto
#endif
+open FsToolkit.ErrorHandling
open SampleDomain
open TestData
open TestHelpers
@@ -130,12 +130,39 @@ let sequenceResultMTests =
let actual = Seq.sequenceResultM (Seq.map Tweet.TryCreate tweets)
- Expect.equal
- actual
- (Error emptyTweetErrMsg)
- "traverse the sequence and return the first error"
+ Expect.equal actual expected "Should have an empty list of valid tweets"
- testCase "sequenceResultM with few invalid data should exit early"
+ testCase "valid data"
+ <| fun _ ->
+ let tweets =
+ seq {
+ "Hi"
+ "Hello"
+ "Hola"
+ }
+
+ let expected = Ok [| for x in tweets -> tweet x |]
+
+ let actual = Seq.sequenceResultM (Seq.map Tweet.TryCreate tweets)
+
+ Expect.equal actual expected "Should have a list of valid tweets"
+
+ testCase "valid and invalid data"
+ <| fun _ ->
+ let tweets =
+ seq {
+ ""
+ "Hello"
+ aLongerInvalidTweet
+ }
+
+ let expected = Error emptyTweetErrMsg
+
+ let actual = Seq.sequenceResultM (Seq.map Tweet.TryCreate tweets)
+
+ Expect.equal actual expected "traverse the sequence and return the first error"
+
+ testCase "stops after first invalid data"
<| fun _ ->
let mutable lastValue = null
@@ -185,12 +212,11 @@ let sequenceOptionMTests =
"Hola"
}
- let expected = Seq.toList tweets
- let actual = Seq.sequenceOptionM (Seq.map tryTweetOption tweets)
+ let expected = Error longerTweetErrMsg
- let actual =
- Expect.wantSome actual "Expected result to be Some"
- |> Seq.toList
+ let actual = Seq.sequenceResultM (Seq.map Tweet.TryCreate tweets)
+
+ Expect.equal actual expected "traverse the sequence and return the first error"
Expect.equal actual expected "Should have a sequence of valid tweets"
@@ -237,55 +263,9 @@ let sequenceOptionMTests =
Expect.equal actual None "traverse the sequence and return none"
]
-let traverseResultATests =
- testList "Seq.traverseResultA Tests" [
- testCase "traverseResultA with a sequence of valid data"
- <| fun _ ->
- let tweets =
- seq {
- "Hi"
- "Hello"
- "Hola"
- }
-
- let expected =
- Seq.map tweet tweets
- |> Seq.toList
-
- let actual = Seq.traverseResultA Tweet.TryCreate tweets
-
- let actual =
- Expect.wantOk actual "Expected result to be Ok"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of valid tweets"
-
- testCase "traverseResultA with few invalid data"
- <| fun _ ->
- let tweets =
- seq {
- ""
- "Hello"
- aLongerInvalidTweet
- }
-
- let actual = Seq.traverseResultA Tweet.TryCreate tweets
-
- let actual =
- Expect.wantError actual "Expected result to be Error"
- |> Seq.toList
-
- let expected = [
- emptyTweetErrMsg
- longerTweetErrMsg
- ]
-
- Expect.equal actual expected "traverse the sequence and return all the errors"
- ]
-
let sequenceResultATests =
testList "Seq.sequenceResultA Tests" [
- testCase "traverseResult with a sequence of valid data"
+ testCase "valid data only"
<| fun _ ->
let tweets =
seq {
@@ -294,440 +274,57 @@ let sequenceResultATests =
"Hola"
}
- let expected =
- Seq.map tweet tweets
- |> Seq.toList
+ let expected = Ok [| for t in tweets -> tweet t |]
let actual = Seq.sequenceResultA (Seq.map Tweet.TryCreate tweets)
- let actual =
- Expect.wantOk actual "Expected result to be Ok"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of valid tweets"
+ Expect.equal actual expected "Should yield an array of valid tweets"
- testCase "sequenceResultM with few invalid data"
+ testCase "valid and multiple invalid data"
<| fun _ ->
- let tweets =
- seq {
- ""
- "Hello"
- aLongerInvalidTweet
- }
-
- let actual = Seq.sequenceResultA (Seq.map Tweet.TryCreate tweets)
-
- let actual =
- Expect.wantError actual "Expected result to be Error"
- |> Seq.toList
-
- let expected = [
- emptyTweetErrMsg
- longerTweetErrMsg
- ]
-
- Expect.equal actual expected "traverse the sequence and return all the errors"
- ]
-
-let userId1 = Guid.NewGuid()
-let userId2 = Guid.NewGuid()
-let userId3 = Guid.NewGuid()
-let userId4 = Guid.NewGuid()
-
-let traverseAsyncResultMTests =
-
- let userIds =
- seq {
- userId1
- userId2
- userId3
- }
- |> Seq.map UserId
-
- testList "Seq.traverseAsyncResultM Tests" [
- testCaseAsync "traverseAsyncResultM with a sequence of valid data"
- <| async {
- let expected =
- userIds
- |> Seq.map (fun (UserId user) -> (newPostId, user))
- |> Seq.toList
-
- let! actual = Seq.traverseAsyncResultM (notifyNewPostSuccess (PostId newPostId)) userIds
-
- let actual =
- Expect.wantOk actual "Expected result to be Ok"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of valid data"
- }
-
- testCaseAsync "traverseResultA with few invalid data"
- <| async {
- let expected = sprintf "error: %s" (userId1.ToString())
-
- let actual =
- Seq.traverseAsyncResultM (notifyNewPostFailure (PostId newPostId)) userIds
-
- do! Expect.hasAsyncErrorValue expected actual
- }
- ]
-
-let traverseAsyncOptionMTests =
-
- let userIds =
- seq {
- userId1
- userId2
- userId3
- }
-
- testList "Seq.traverseAsyncOptionM Tests" [
- testCaseAsync "traverseAsyncOptionM with a sequence of valid data"
- <| async {
- let expected =
- userIds
- |> Seq.toList
- |> Some
-
- let f x = async { return Some x }
-
- let actual =
- Seq.traverseAsyncOptionM f userIds
- |> AsyncOption.map Seq.toList
-
- match expected with
- | Some e -> do! Expect.hasAsyncSomeValue e actual
- | None -> failwith "Error in the test case code"
- }
-
- testCaseAsync "traverseOptionA with few invalid data"
- <| async {
- let expected = None
- let f _ = async { return None }
- let actual = Seq.traverseAsyncOptionM f userIds
-
- match expected with
- | Some _ -> failwith "Error in the test case code"
- | None -> do! Expect.hasAsyncNoneValue actual
- }
- ]
-
-let notifyFailure (PostId _) (UserId uId) =
- async {
- if
- (uId = userId1
- || uId = userId3)
- then
- return
- sprintf "error: %s" (uId.ToString())
- |> Error
- else
- return Ok()
- }
-
-
-let traverseAsyncResultATests =
- let userIds =
- seq {
- userId1
- userId2
- userId3
- userId4
- }
- |> Seq.map UserId
-
- testList "Seq.traverseAsyncResultA Tests" [
- testCaseAsync "traverseAsyncResultA with a sequence of valid data"
- <| async {
- let expected =
- userIds
- |> Seq.map (fun (UserId user) -> (newPostId, user))
- |> Seq.toList
-
- let! actual = Seq.traverseAsyncResultA (notifyNewPostSuccess (PostId newPostId)) userIds
-
- let actual =
- Expect.wantOk actual "Expected result to be Ok"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of valid data"
- }
-
- testCaseAsync "traverseResultA with few invalid data"
- <| async {
- let expected = [
- sprintf "error: %s" (userId1.ToString())
- sprintf "error: %s" (userId3.ToString())
+ let tweets = [
+ ""
+ "Hello"
+ aLongerInvalidTweet
]
- let! actual = Seq.traverseAsyncResultA (notifyFailure (PostId newPostId)) userIds
-
- let actual =
- Expect.wantError actual "Expected result to be Error"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of errors"
- }
- ]
-
-
-let sequenceAsyncResultMTests =
- let userIds =
- seq {
- userId1
- userId2
- userId3
- userId4
- }
- |> Seq.map UserId
-
- testList "Seq.sequenceAsyncResultM Tests" [
- testCaseAsync "sequenceAsyncResultM with a sequence of valid data"
- <| async {
- let expected =
- userIds
- |> Seq.map (fun (UserId user) -> (newPostId, user))
- |> Seq.toList
-
- let! actual =
- Seq.map (notifyNewPostSuccess (PostId newPostId)) userIds
- |> Seq.sequenceAsyncResultM
-
- let actual =
- Expect.wantOk actual "Expected result to be Ok"
- |> Seq.toList
-
- Expect.equal actual expected "Should have a sequence of valid data"
- }
-
- testCaseAsync "sequenceAsyncResultM with few invalid data"
- <| async {
- let expected = sprintf "error: %s" (userId1.ToString())
-
- let actual =
- Seq.map (notifyFailure (PostId newPostId)) userIds
- |> Seq.sequenceAsyncResultM
-
- do! Expect.hasAsyncErrorValue expected actual
- }
- ]
-
-let sequenceAsyncOptionMTests =
-
- let userIds =
- seq {
- userId1
- userId2
- userId3
- }
-
- testList "Seq.sequenceAsyncOptionM Tests" [
- testCaseAsync "sequenceAsyncOptionM with a sequence of valid data"
- <| async {
let expected =
- Seq.toList userIds
- |> Some
-
- let f x = async { return Some x }
+ Error [|
+ emptyTweetErrMsg
+ longerTweetErrMsg
+ |]
- let actual =
- Seq.map f userIds
- |> Seq.sequenceAsyncOptionM
- |> AsyncOption.map Seq.toList
-
- match expected with
- | Some e -> do! Expect.hasAsyncSomeValue e actual
- | None -> failwith "Error in the test case code"
- }
-
- testCaseAsync "sequenceOptionA with few invalid data"
- <| async {
- let expected = None
- let f _ = async { return None }
-
- let actual =
- Seq.map f userIds
- |> Seq.sequenceAsyncOptionM
-
- match expected with
- | Some _ -> failwith "Error in the test case code"
- | None -> do! Expect.hasAsyncNoneValue actual
- }
- ]
-
-let sequenceAsyncResultATests =
- let userIds =
- seq {
- userId1
- userId2
- userId3
- userId4
- }
- |> Seq.map UserId
-
- testList "Seq.sequenceAsyncResultA Tests" [
- testCaseAsync "sequenceAsyncResultA with a sequence of valid data"
- <| async {
- let expected =
- userIds
- |> Seq.map (fun (UserId user) -> (newPostId, user))
- |> Seq.toList
-
- let actual =
- Seq.map (notifyNewPostSuccess (PostId newPostId)) userIds
- |> Seq.sequenceAsyncResultA
- |> AsyncResult.map Seq.toList
-
- do! Expect.hasAsyncOkValue expected actual
- }
-
- testCaseAsync "sequenceAsyncResultA with few invalid data"
- <| async {
- let expected = [
- sprintf "error: %s" (userId1.ToString())
- sprintf "error: %s" (userId3.ToString())
- ]
-
- let! actual =
- Seq.map (notifyFailure (PostId newPostId)) userIds
- |> Seq.sequenceAsyncResultA
- |> AsyncResult.mapError Seq.toList
-
- let actual = Expect.wantError actual "Expected result to be Error"
- Expect.equal actual expected "Should have a sequence of errors"
- }
- ]
-
-#if !FABLE_COMPILER
-let traverseVOptionMTests =
- testList "Seq.traverseVOptionM Tests" [
- let tryTweetVOption x =
- match x with
- | x when String.IsNullOrEmpty x -> ValueNone
- | _ -> ValueSome x
-
- testCase "traverseVOption with a sequence of valid data"
- <| fun _ ->
- let tweets =
- seq {
- "Hi"
- "Hello"
- "Hola"
- }
-
- let expected = Seq.toList tweets
-
- let actual =
- Seq.traverseVOptionM tryTweetVOption tweets
- |> ValueOption.map Seq.toList
+ let actual = Seq.sequenceResultA (Seq.map Tweet.TryCreate tweets)
- match actual with
- | ValueSome actual ->
- Expect.equal actual expected "Should have a sequence of valid tweets"
- | ValueNone -> failwith "Expected a value some"
+ Expect.equal actual expected "traverse the seq and return all the errors"
- testCase "traverseVOption with few invalid data"
+ testCase "iterates exacly once"
<| fun _ ->
- let tweets =
- seq {
- "Hi"
- "Hello"
- String.Empty
- }
+ let mutable counter = 0
- let actual = Seq.traverseVOptionM tryTweetVOption tweets
- Expect.equal actual ValueNone "traverse the sequence and return value none"
- ]
-
-let sequenceVOptionMTests =
- testList "Seq.sequenceVOptionM Tests" [
- let tryTweetOption x =
- match x with
- | x when String.IsNullOrEmpty x -> ValueNone
- | _ -> ValueSome x
-
- testCase "traverseVOption with a sequence of valid data"
- <| fun _ ->
let tweets =
seq {
"Hi"
"Hello"
"Hola"
- }
-
- let expected = Seq.toList tweets
-
- let actual =
- Seq.sequenceVOptionM (Seq.map tryTweetOption tweets)
- |> ValueOption.map Seq.toList
-
- match actual with
- | ValueSome actual ->
- Expect.equal actual expected "Should have a sequence of valid tweets"
- | ValueNone -> failwith "Expected a value some"
-
- testCase "sequenceVOptionM with few invalid data"
- <| fun _ ->
- let tweets =
- seq {
- String.Empty
- "Hello"
- String.Empty
- }
-
- let actual = Seq.sequenceVOptionM (Seq.map tryTweetOption tweets)
- Expect.equal actual ValueNone "traverse the sequence and return value none"
-
- testCase "sequenceVOptionM with few invalid data should exit early"
- <| fun _ ->
-
- let mutable lastValue = null
- let mutable callCount = 0
-
- let tweets =
- seq {
- ""
- "Hello"
aLongerInvalidTweet
- }
- let tryCreate tweet =
- callCount <-
- callCount
- + 1
+ counter <-
+ counter
+ + 1
+ }
- match tweet with
- | x when String.IsNullOrEmpty x -> ValueNone
- | x -> ValueSome x
+ let expected = Error [| longerTweetErrMsg |]
- let actual = Seq.sequenceVOptionM (Seq.map tryCreate tweets)
+ let actual = Seq.sequenceResultA (Seq.map Tweet.TryCreate tweets)
- match actual with
- | ValueNone -> ()
- | ValueSome _ -> failwith "Expected a value none"
+ Expect.equal actual expected "traverse the seq and return all the errors"
- Expect.equal callCount 1 "Should have called the function only 1 time"
- Expect.equal lastValue null ""
+ Expect.equal counter 1 "evaluation of the sequence completes exactly once"
]
-#endif
-
let allTests =
- testList "List Tests" [
- traverseResultMTests
- traverseOptionMTests
+ testList "Seq Tests" [
sequenceResultMTests
- sequenceOptionMTests
- traverseResultATests
sequenceResultATests
- traverseAsyncResultMTests
- traverseAsyncOptionMTests
- traverseAsyncResultATests
- sequenceAsyncResultMTests
- sequenceAsyncOptionMTests
- sequenceAsyncResultATests
-#if !FABLE_COMPILER
- traverseVOptionMTests
- sequenceVOptionMTests
-#endif
]