You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While most of the above have trivial semantics and should sometimes take an Async overload (i.e., findIndexAsync and initAsync for the lambda), I'm not entirely sure of the usefulness of TaskSeq.cache (and we already have TaskSeq.toSeqCached), but perhaps for parity it should be included.
A note on TaskSeq.cast vs Seq.cast
While the docs on Seq.cast say that it is meant for a "loosely typed sequence", to be cast to a generically strongly typed sequence, it can be used just fine to cast an F# seq, because it also implements IEnumerable (i.e., the non-generic variant).
// this is fineletx:seq<uint>=seq{1}|> Seq.cast
But F# also allows you to perform an illegal cast:
// this won't give any warnings, but will throw an exceptionletx:seq<Guid>=seq{1}|> Seq.cast
Since IAsyncEnumerable<'T> only exists as a typed sequence, we should honor that and only allow valid casts. However, F# doesn't allow a constraint like 'T :> 'U, the rh-side must be a concrete type. This means that in the end, it'll effectively work the same way as for Seq.cast through boxing. Alternatively, if the type-relation is known ahead of time, users should probably just write TaskSeq.map (fun x -> x :> _) just as they would for seq<_>.
// this is fineletx:seq<uint>= taskSeq {1}|> TaskSeq.cast
// this *should* raise a compile-time exception, but there's no way to enforce thatletx:seq<Guid>= taskSeq {1}|> TaskSeq.cast // incompatible
For comparison, Linq.Enumerable.Cast works through the untyped Enumerable as well.
EDIT: to get better parity with Seq.cast and Linq.Enumerable.Cast, I decided to only allow it to work with untyped task sequences (that is: IAsyncEnumerable<obj>). I've updated the signature below. In addition, we'll be adding a box and unbox helper as well, the latter only for value types. If users want a reinterpret_cast style cast, they can use TaskSeq.box >> TaskSeq.cast. Due to the static way this is compiled, this won't add overhead.
While most of the above have trivial semantics and should sometimes take an
Asyncoverload (i.e.,findIndexAsyncandinitAsyncfor the lambda), I'm not entirely sure of the usefulness ofTaskSeq.cache(and we already haveTaskSeq.toSeqCached), but perhaps for parity it should be included.A note on
TaskSeq.castvsSeq.castWhile the docs on
Seq.castsay that it is meant for a "loosely typed sequence", to be cast to a generically strongly typed sequence, it can be used just fine to cast an F#seq, because it also implementsIEnumerable(i.e., the non-generic variant).But F# also allows you to perform an illegal cast:
Since
IAsyncEnumerable<'T>only exists as a typed sequence, we should honor that and only allow valid casts. However, F# doesn't allow a constraint like'T :> 'U, the rh-side must be a concrete type. This means that in the end, it'll effectively work the same way as forSeq.castthrough boxing. Alternatively, if the type-relation is known ahead of time, users should probably just writeTaskSeq.map (fun x -> x :> _)just as they would forseq<_>.For comparison,
Linq.Enumerable.Castworks through the untypedEnumerableas well.EDIT: to get better parity with
Seq.castandLinq.Enumerable.Cast, I decided to only allow it to work with untyped task sequences (that is:IAsyncEnumerable<obj>). I've updated the signature below. In addition, we'll be adding aboxandunboxhelper as well, the latter only for value types. If users want areinterpret_caststyle cast, they can useTaskSeq.box >> TaskSeq.cast. Due to the static way this is compiled, this won't add overhead.TODO list:
length, see Increase surface area: TaskSeq.length, lengthBy and lengthByAsync #53lengthBy, see Increase surface area: TaskSeq.length, lengthBy and lengthByAsync #53lengthByAsync, see Increase surface area: TaskSeq.length, lengthBy and lengthByAsync #53allPairs// later, requirescacheto be implementedindexed, see AddTaskSeq.indexed,findIndex,tryFindIndex,findIndexAsync,tryFindIndexAsync#68cache// later, see MBP approach of AsyncSeqcast, see Add more surface area functions:TaskSeq.cast,boxandunbox#67box, see Add more surface area functions:TaskSeq.cast,boxandunbox#67unbox, see Add more surface area functions:TaskSeq.cast,boxandunbox#67concat, see ImplementTaskSeq.init,initAsync,initInfinite,initInfiniteAsyncandTaskSeq.concat#69findIndex, see AddTaskSeq.indexed,findIndex,tryFindIndex,findIndexAsync,tryFindIndexAsync#68findIndexAsync, see AddTaskSeq.indexed,findIndex,tryFindIndex,findIndexAsync,tryFindIndexAsync#68tryFindIndex, see AddTaskSeq.indexed,findIndex,tryFindIndex,findIndexAsync,tryFindIndexAsync#68tryFindIndexAsync, see AddTaskSeq.indexed,findIndex,tryFindIndex,findIndexAsync,tryFindIndexAsync#68containsexistsexistsAsyncinit, see ImplementTaskSeq.init,initAsync,initInfinite,initInfiniteAsyncandTaskSeq.concat#69initAsync, see ImplementTaskSeq.init,initAsync,initInfinite,initInfiniteAsyncandTaskSeq.concat#69initInifinite, see ImplementTaskSeq.init,initAsync,initInfinite,initInfiniteAsyncandTaskSeq.concat#69initInifiniteAsync, see ImplementTaskSeq.init,initAsync,initInfinite,initInfiniteAsyncandTaskSeq.concat#69Proposals of signatures: