diff --git a/src/FSharp.Control.TaskSeq.sln.DotSettings b/src/FSharp.Control.TaskSeq.sln.DotSettings
new file mode 100644
index 00000000..a8d97860
--- /dev/null
+++ b/src/FSharp.Control.TaskSeq.sln.DotSettings
@@ -0,0 +1,5 @@
+
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/src/FSharp.Control.TaskSeq/TaskSeq.fs b/src/FSharp.Control.TaskSeq/TaskSeq.fs
index d3aedcb9..d1819e31 100644
--- a/src/FSharp.Control.TaskSeq/TaskSeq.fs
+++ b/src/FSharp.Control.TaskSeq/TaskSeq.fs
@@ -314,15 +314,15 @@ type TaskSeq private () =
static member exists predicate source =
Internal.tryFind (Predicate predicate) source
- |> Task.map (Option.isSome)
+ |> Task.map Option.isSome
static member existsAsync predicate source =
Internal.tryFind (PredicateAsync predicate) source
- |> Task.map (Option.isSome)
+ |> Task.map Option.isSome
static member contains value source =
Internal.tryFind (Predicate((=) value)) source
- |> Task.map (Option.isSome)
+ |> Task.map Option.isSome
static member pick chooser source =
Internal.tryPick (TryPick chooser) source
@@ -348,8 +348,6 @@ type TaskSeq private () =
Internal.tryFindIndex (PredicateAsync predicate) source
|> Task.map (Option.defaultWith Internal.raiseNotFound)
-
-
//
// zip/unzip/fold etc functions
//
diff --git a/src/FSharp.Control.TaskSeq/TaskSeq.fsi b/src/FSharp.Control.TaskSeq/TaskSeq.fsi
index c34895d2..e452dd0c 100644
--- a/src/FSharp.Control.TaskSeq/TaskSeq.fsi
+++ b/src/FSharp.Control.TaskSeq/TaskSeq.fsi
@@ -81,7 +81,7 @@ type TaskSeq =
///
/// Generates a new task sequence which, when iterated, will return successive elements by calling the given function
- /// with the curren zero-basedt index, up to the given count. Each element is saved after its initialization for successive access to
+ /// with the current zero-based index, up to the given count. Each element is saved after its initialization for successive access to
/// , which will not re-evaluate the . However,
/// re-iterating the returned task sequence will re-evaluate the initialization function. The returned sequence may
/// be passed between threads safely. However, individual IEnumerator values generated from the returned sequence should
@@ -454,58 +454,58 @@ type TaskSeq =
static member indexed: source: TaskSeq<'T> -> TaskSeq
///
- /// Builds a new task sequence whose elements are the results of applying the
+ /// Builds a new task sequence whose elements are the results of applying the
/// function to each of the elements of the input task sequence in .
/// The given function will be applied as elements are pulled using the
/// method on async enumerators retrieved from the input task sequence.
/// Does not evaluate the input sequence until requested.
///
///
- /// A function to transform items from the input task sequence.
+ /// A function to transform items from the input task sequence.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
static member map: mapper: ('T -> 'U) -> source: TaskSeq<'T> -> TaskSeq<'U>
///
- /// Builds a new task sequence whose elements are the results of applying the
+ /// Builds a new task sequence whose elements are the results of applying the
/// function to each of the elements of the input task sequence in , passing
- /// an extra zero-based index argument to the function.
+ /// an extra zero-based index argument to the function.
/// The given function will be applied as elements are pulled using the
/// method on async enumerators retrieved from the input task sequence.
/// Does not evaluate the input sequence until requested.
///
///
- /// A function to transform items from the input task sequence that also access the current index.
+ /// A function to transform items from the input task sequence that also access the current index.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
static member mapi: mapper: (int -> 'T -> 'U) -> source: TaskSeq<'T> -> TaskSeq<'U>
///
- /// Builds a new task sequence whose elements are the results of applying the asynchronous
+ /// Builds a new task sequence whose elements are the results of applying the asynchronous
/// function to each of the elements of the input task sequence in .
/// The given function will be applied as elements are pulled using the
/// method on async enumerators retrieved from the input task sequence.
/// Does not evaluate the input sequence until requested.
///
///
- /// An asynchronous function to transform items from the input task sequence.
+ /// An asynchronous function to transform items from the input task sequence.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
static member mapAsync: mapper: ('T -> #Task<'U>) -> source: TaskSeq<'T> -> TaskSeq<'U>
///
- /// Builds a new task sequence whose elements are the results of applying the asynchronous
+ /// Builds a new task sequence whose elements are the results of applying the asynchronous
/// function to each of the elements of the input task sequence in , passing
- /// an extra zero-based index argument to the function.
+ /// an extra zero-based index argument to the function.
/// The given function will be applied as elements are pulled using the
/// method on async enumerators retrieved from the input task sequence.
/// Does not evaluate the input sequence until requested.
///
///
- /// An asynchronous function to transform items from the input task sequence that also access the current index.
+ /// An asynchronous function to transform items from the input task sequence that also access the current index.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
@@ -640,6 +640,7 @@ type TaskSeq =
///
///
/// The input task sequence.
+ /// The index of the item to retrieve.
/// The nth element of the task sequence, or None if it doesn't exist.
/// Thrown when the input task sequence is null.
static member tryItem: index: int -> source: TaskSeq<'T> -> Task<'T option>
@@ -651,6 +652,7 @@ type TaskSeq =
///
///
/// The input task sequence.
+ /// The index of the item to retrieve.
/// The nth element of the task sequence.
/// Thrown when the input task sequence is null.
/// Thrown when the sequence has insufficient length or is negative.
@@ -818,7 +820,7 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, yields elements of the underlying sequence while the
/// given function returns , and then returns no further elements.
- /// The first element where the predicate returns is not included in the resulting sequence
+ /// Stops consuming the source and yielding items as soon as the predicate returns false.
/// (see also ).
/// If is asynchronous, consider using .
///
@@ -832,7 +834,7 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, yields elements of the underlying sequence while the
/// given asynchronous function returns , and then returns no further elements.
- /// The first element where the predicate returns is not included in the resulting sequence
+ /// Stops consuming the source and yielding items as soon as the predicate returns false.
/// (see also ).
/// If is synchronous, consider using .
///
@@ -874,8 +876,8 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, skips elements of the underlying sequence while the
/// given function returns , and then yields the remaining
- /// elements. The first element where the predicate returns is returned, which means that this
- /// function will skip 0 or more elements (see also ).
+ /// elements. Elements where the predicate returns are propagated, which means that this
+ /// function may not skip any elements (see also ).
/// If is asynchronous, consider using .
///
///
@@ -888,8 +890,8 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, skips elements of the underlying sequence while the
/// given asynchronous function returns , and then yields the
- /// remaining elements. The first element where the predicate returns is returned, which
- /// means that this function will skip 0 or more elements (see also ).
+ /// remaining elements. Elements where the predicate returns are propagated, which means that this
+ /// function may not skip any elements (see also ).
/// If is synchronous, consider using .
///
///
@@ -901,13 +903,13 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, skips elements of the underlying sequence until the given
- /// function returns , also skips that element
- /// and then yields the remaining elements (see also ). This function skips
+ /// function returns , also skips that element
+ /// and then yields the remaining elements (see also ). It will thus always skip
/// at least one element of a non-empty sequence, or returns the empty task sequence if the input is empty.
/// If is asynchronous, consider using .
/// `
///
- /// A function that evaluates to false when no more items should be skipped.
+ /// A function that evaluates to false for the final item to be skipped.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
@@ -915,13 +917,13 @@ type TaskSeq =
///
/// Returns a task sequence that, when iterated, skips elements of the underlying sequence until the given
- /// function returns , also skips that element
- /// and then yields the remaining elements (see also ). This function skips
+ /// function returns , also skips that element
+ /// and then yields the remaining elements (see also ). It will thus always skip
/// at least one element of a non-empty sequence, or returns the empty task sequence if the input is empty.
/// If is synchronous, consider using .
///
///
- /// An asynchronous function that evaluates to false when no more items should be skipped.
+ /// An asynchronous function that evaluates to false for the final item to be skipped.
/// The input task sequence.
/// The resulting task sequence.
/// Thrown when the input task sequence is null.
@@ -1163,8 +1165,8 @@ type TaskSeq =
///
/// Applies the function to each element in the task sequence, threading an accumulator
- /// argument of type through the computation. If the input function is and the elements are
- /// then computes .
+ /// argument of type through the computation. If the input function is f
and the elements are i0...iN
+ /// then computes f (... (f s i0)...) iN
.
/// If the accumulator function is asynchronous, consider using .
///
///
@@ -1177,8 +1179,8 @@ type TaskSeq =
///
/// Applies the asynchronous function to each element in the task sequence, threading an accumulator
- /// argument of type through the computation. If the input function is and the elements are
- /// then computes .
+ /// argument of type through the computation. If the input function is f
and the elements are i0...iN
+ /// then computes f (... (f s i0)...) iN
.
/// If the accumulator function is synchronous, consider using .
///
///
diff --git a/src/FSharp.Control.TaskSeq/TaskSeqInternal.fs b/src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
index e59d50c3..ed92a9fe 100644
--- a/src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
+++ b/src/FSharp.Control.TaskSeq/TaskSeqInternal.fs
@@ -163,7 +163,6 @@ module internal TaskSeqInternal =
checkNonNull (nameof source) source
task {
-
use e = source.GetAsyncEnumerator CancellationToken.None
let mutable go = true
let mutable i = 0
@@ -178,6 +177,77 @@ module internal TaskSeqInternal =
return i
}
+ let inline maxMin ([] maxOrMin) (source: TaskSeq<_>) =
+ checkNonNull (nameof source) source
+
+ task {
+ use e = source.GetAsyncEnumerator CancellationToken.None
+ let! nonEmpty = e.MoveNextAsync()
+
+ if not nonEmpty then
+ raiseEmptySeq ()
+
+ let mutable acc = e.Current
+
+ while! e.MoveNextAsync() do
+ acc <- maxOrMin e.Current acc
+
+ return acc
+ }
+
+ // 'compare' is either `<` or `>` (i.e, less-than, greater-than resp.)
+ let inline maxMinBy ([] compare) ([] projection) (source: TaskSeq<_>) =
+ checkNonNull (nameof source) source
+
+ task {
+ use e = source.GetAsyncEnumerator CancellationToken.None
+ let! nonEmpty = e.MoveNextAsync()
+
+ if not nonEmpty then
+ raiseEmptySeq ()
+
+ let value = e.Current
+ let mutable accProjection = projection value
+ let mutable accValue = value
+
+ while! e.MoveNextAsync() do
+ let value = e.Current
+ let currentProjection = projection value
+
+ if compare accProjection currentProjection then
+ accProjection <- currentProjection
+ accValue <- value
+
+ return accValue
+ }
+
+ // 'compare' is either `<` or `>` (i.e, less-than, greater-than resp.)
+ let inline maxMinByAsync ([] compare) ([] projectionAsync) (source: TaskSeq<_>) =
+ checkNonNull (nameof source) source
+
+ task {
+ use e = source.GetAsyncEnumerator CancellationToken.None
+ let! nonEmpty = e.MoveNextAsync()
+
+ if not nonEmpty then
+ raiseEmptySeq ()
+
+ let value = e.Current
+ let! projValue = projectionAsync value
+ let mutable accProjection = projValue
+ let mutable accValue = value
+
+ while! e.MoveNextAsync() do
+ let value = e.Current
+ let! currentProjection = projectionAsync value
+
+ if compare accProjection currentProjection then
+ accProjection <- currentProjection
+ accValue <- value
+
+ return accValue
+ }
+
let tryExactlyOne (source: TaskSeq<_>) =
checkNonNull (nameof source) source