Skip to content

Commit 779b073

Browse files
author
Jay Goldstein
committed
WIP src and test cases
1 parent 3244da4 commit 779b073

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/FsToolkit.ErrorHandling/Option.fs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,11 @@ module Option =
321321

322322
opt
323323

324+
/// <summary>
324325
/// Converts a Option<Async<_>> to an Async<Option<_>>
326+
///
327+
/// Documentation is found here: <href>https://demystifyfp.gitbook.io/fstoolkit-errorhandling/fstoolkit.errorhandling/option/sequenceasync</href>
328+
/// </summary>
325329
let inline sequenceAsync (optAsync: Option<Async<'T>>) : Async<Option<'T>> =
326330
async {
327331
match optAsync with
@@ -333,6 +337,8 @@ module Option =
333337

334338
/// <summary>
335339
/// Maps an Async function over an Option, returning an Async Option.
340+
///
341+
/// Documentation is found here: <href>https://demystifyfp.gitbook.io/fstoolkit-errorhandling/fstoolkit.errorhandling/option/traverseasync</href>
336342
/// </summary>
337343
/// <param name="f">The function to map over the Option.</param>
338344
/// <param name="opt">The Option to map over.</param>
@@ -343,6 +349,35 @@ module Option =
343349
: Async<Option<'T>> =
344350
sequenceAsync ((map f) opt)
345351

352+
/// <summary>
353+
/// Converts a Option<Async<Result<'ok,'error>>> to an Async<Result<Option<'ok>,'error>>
354+
/// </summary>
355+
let inline sequenceAsyncResult
356+
(optAsyncResult: Option<Async<Result<'T, 'E>>>)
357+
: Async<Result<Option<'T>, 'E>> =
358+
async {
359+
match optAsyncResult with
360+
| Some asncRes ->
361+
let! xRes = asncRes
362+
363+
return
364+
xRes
365+
|> Result.map Some
366+
| None -> return Ok None
367+
}
368+
369+
/// <summary>
370+
/// Maps an AsyncResult function over an Option, returning an AsyncResult Option.
371+
/// </summary>
372+
/// <param name="f">The function to map over the Option.</param>
373+
/// <param name="opt">The Option to map over.</param>
374+
/// <returns>An AsyncResult Option with the mapped value.</returns>
375+
let inline traverseAsyncResult
376+
([<InlineIfLambda>] f: 'T -> Async<Result<'U, 'E>>)
377+
(opt: Option<'T>)
378+
: Async<Result<Option<'U>, 'E>> =
379+
sequenceAsyncResult ((map f) opt)
380+
346381
/// <summary>
347382
/// Creates an option from a boolean value and a value of type 'a.
348383
/// If the boolean value is true, returns <c>Some</c> value.

tests/FsToolkit.ErrorHandling.Tests/Option.fs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,52 @@ let sequenceAsyncTests =
211211
}
212212
]
213213

214+
let sequenceAsyncResultTests =
215+
ftestList "Option.sequenceAsyncResult Tests" [
216+
testCaseAsync "sequenceAsyncResult returns the async Ok value if Some"
217+
<| async {
218+
let optAsyncOk =
219+
async { return Ok "foo" }
220+
|> Some
221+
222+
let! valueRes =
223+
optAsyncOk
224+
|> Option.sequenceAsyncResult
225+
226+
let value = Expect.wantOk valueRes "Expect to get back OK"
227+
Expect.equal value (Some "foo") "Expect to get back value"
228+
}
229+
230+
testCaseAsync "sequenceAsyncResult returns the async Error value if Some"
231+
<| async {
232+
let optAsyncOk =
233+
async { return Error "error" }
234+
|> Some
235+
236+
let! valueRes =
237+
optAsyncOk
238+
|> Option.sequenceAsyncResult
239+
240+
let errorValue = Expect.wantError valueRes "Expect to get back Error"
241+
Expect.equal errorValue "error" "Expect to get back the error value"
242+
}
243+
244+
testCaseAsync "sequenceAsyncResult returns None if None"
245+
<| async {
246+
let optAsyncNone = None
247+
248+
let! valueRes =
249+
optAsyncNone
250+
|> Option.sequenceAsyncResult
251+
252+
let valueNone = Expect.wantOk valueRes "Expect to get back OK"
253+
Expect.isNone valueNone "Expect to get back None"
254+
255+
// check things actually fail when fail
256+
Expect.isSome valueNone "This should fail"
257+
}
258+
]
259+
214260
let traverseAsyncTests =
215261
testList "Option.traverseAsync Tests" [
216262
testCaseAsync "traverseAsync returns the async value if Some"
@@ -259,6 +305,23 @@ let traverseResultTests =
259305
|> Expect.hasOkValue (Some validLng)
260306
]
261307

308+
// to do
309+
// let traverseAsyncResultTests =
310+
// testList "Option.traverseAsyncResult Tests" [
311+
// testCaseAsync "traverseAsyncResult with valid latitute data"
312+
// <| async {
313+
// let tryCreateLatAsync = fun l -> async { return Latitude.TryCreate l }
314+
//
315+
// let! valueRes =
316+
// Some lat
317+
// |> Option.traverseAsyncResult tryCreateLatAsync
318+
//
319+
// let value = Expect.wantOk valueRes "Expect to get OK"
320+
// Expect.equal value (Some validLat) "Expect to get valid latitute"
321+
//
322+
// }
323+
//
324+
// ]
262325

263326
let tryParseTests =
264327
testList "Option.tryParse" [

0 commit comments

Comments
 (0)