Skip to content

Commit

Permalink
Added sequence and traverse VOptionM
Browse files Browse the repository at this point in the history
  • Loading branch information
1eyewonder authored and TheAngryByrd committed Nov 11, 2023
1 parent 75bdb37 commit deda884
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/FsToolkit.ErrorHandling/List.fs
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,24 @@ module List =
traverseAsyncOptionM' (AsyncOption.retn []) f xs

let sequenceAsyncOptionM xs = traverseAsyncOptionM id xs

let rec private traverseVOptionM' (state: voption<_>) (f: _ -> voption<_>) xs =
match xs with
| [] ->
state
|> ValueOption.map List.rev
| x :: xs ->
let r =
voption {
let! y = f x
let! ys = state
return y :: ys
}

match r with
| ValueSome _ -> traverseVOptionM' r f xs
| ValueNone -> r

let traverseVOptionM f xs = traverseVOptionM' (ValueSome []) f xs

let sequenceVOptionM xs = traverseVOptionM id xs
66 changes: 66 additions & 0 deletions tests/FsToolkit.ErrorHandling.Tests/List.fs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,70 @@ let sequenceAsyncResultATests =
}
]

let traverseVOptionMTests =
testList "List.traverseVOptionM Tests" [
let tryTweetVOption x =
match x with
| x when String.IsNullOrEmpty x -> ValueNone
| _ -> ValueSome x

testCase "traverseVOption with a list of valid data"
<| fun _ ->
let tweets = [
"Hi"
"Hello"
"Hola"
]

let expected = ValueSome tweets
let actual = List.traverseVOptionM tryTweetVOption tweets

Expect.equal actual expected "Should have a list of valid tweets"

testCase "traverseVOption with few invalid data"
<| fun _ ->
let tweets = [
"Hi"
"Hello"
String.Empty
]

let actual = List.traverseVOptionM tryTweetVOption tweets
Expect.equal actual ValueNone "traverse the list and return value none"
]

let sequenceVOptionMTests =
testList "List.sequenceVOptionM Tests" [
let tryTweetOption x =
match x with
| x when String.IsNullOrEmpty x -> ValueNone
| _ -> ValueSome x

testCase "traverseVOption with a list of valid data"
<| fun _ ->
let tweets = [
"Hi"
"Hello"
"Hola"
]

let expected = ValueSome tweets
let actual = List.sequenceVOptionM (List.map tryTweetOption tweets)

Expect.equal actual expected "Should have a list of valid tweets"

testCase "sequenceVOptionM with few invalid data"
<| fun _ ->
let tweets = [
String.Empty
"Hello"
String.Empty
]

let actual = List.sequenceVOptionM (List.map tryTweetOption tweets)
Expect.equal actual ValueNone "traverse the list and return value none"
]

let allTests =
testList "List Tests" [
traverseResultMTests
Expand All @@ -563,4 +627,6 @@ let allTests =
sequenceAsyncResultMTests
sequenceAsyncOptionMTests
sequenceAsyncResultATests
traverseVOptionMTests
sequenceVOptionMTests
]

0 comments on commit deda884

Please sign in to comment.