Last active
February 9, 2023 23:13
-
-
Save ruxo/77ef3fa1e43235a64db1f5c3362093f2 to your computer and use it in GitHub Desktop.
F# Task Sequence implementation attempt..
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module rec TiraxTech.Foundation | |
| open System | |
| open System.Collections.Generic | |
| open System.Threading.Tasks | |
| open IdentityServer4.Models | |
| open TiraxTech.Foundation | |
| module AsyncEnumerator = | |
| let Empty<'T>() = { new IAsyncEnumerator<'T> with | |
| member _.Current: 'T = raise <| NotSupportedException() | |
| member _.MoveNextAsync() = ValueTask<bool>(false) | |
| interface IAsyncDisposable with | |
| member _.DisposeAsync() = ValueTask.CompletedTask | |
| } | |
| type private AsyncEnumFromTask<'T>(t: Task<'T>) = | |
| let mutable fetched: 'T option = None | |
| interface IAsyncEnumerator<'T> with | |
| member _.Current = fetched.Value | |
| member _.MoveNextAsync() = | |
| task { | |
| match fetched with | |
| | Some _ -> return false | |
| | None -> let! result = t | |
| fetched <- Some result | |
| return true | |
| } |> ValueTask<bool> | |
| interface IAsyncDisposable with | |
| member _.DisposeAsync() = ValueTask.CompletedTask | |
| type private AsyncEnumFromValue<'T>(v: 'T) = | |
| let mutable fetched = false | |
| interface IAsyncEnumerator<'T> with | |
| member _.Current = v | |
| member _.MoveNextAsync() = | |
| let current = fetched | |
| fetched <- true | |
| ValueTask<bool>(current) | |
| interface IAsyncDisposable with | |
| member _.DisposeAsync() = ValueTask.CompletedTask | |
| type private AsyncEnumFromItor<'T,'Result>(itor: IEnumerator<'T>, f) = | |
| interface IAsyncEnumerator<'Result> with | |
| member _.Current = f itor.Current | |
| member _.MoveNextAsync() = ValueTask<bool>(itor.MoveNext()) | |
| interface IAsyncDisposable with | |
| member _.DisposeAsync() = | |
| itor.Dispose() | |
| ValueTask.CompletedTask | |
| type private AsyncEnumFromSeq<'T, 'Result>(xseq: 'T seq, f) = | |
| interface IAsyncEnumerable<'Result> with | |
| member _.GetAsyncEnumerator(_) = AsyncEnumFromItor(xseq.GetEnumerator(), f) | |
| type private AsyncEnumOf<'T>(f) = | |
| interface IAsyncEnumerable<'T> with | |
| member _.GetAsyncEnumerator(cancelletionToken) = f cancelletionToken | |
| type SeqItem<'T> = | |
| | Value of 'T | |
| | TaskValue of Task<'T> | |
| | Delayed of (unit -> AsyncEnum<'T>) | |
| let private createItor = function | |
| | Value x -> AsyncEnumFromValue(x) :> IAsyncEnumerator<'T> | |
| | TaskValue t -> AsyncEnumFromTask(t) | |
| type private AsyncIterator<'T>(xseq: IEnumerator<SeqItem<'T>>) = | |
| let mutable iterator: IAsyncEnumerator<'T> = AsyncEnumerator.Empty<'T>() | |
| let rec moveNext() = | |
| task { | |
| let! next = iterator.MoveNextAsync() | |
| if next then | |
| return true | |
| elif xseq.MoveNext() then | |
| iterator <- createItor xseq.Current | |
| return! moveNext() | |
| else | |
| return false | |
| } | |
| interface IAsyncEnumerator<'T> with | |
| member _.Current = iterator.Current | |
| member my.MoveNextAsync() = moveNext() |> ValueTask<bool> | |
| interface IAsyncDisposable with | |
| member _.DisposeAsync() = ValueTask.CompletedTask | |
| type AsyncEnum<'T>(xseq: SeqItem<'T> seq) = | |
| new(item) = AsyncEnum<'T>(Seq.singleton item) | |
| member private _.Source = xseq | |
| member my.Combine(other: AsyncEnum<'T>) = AsyncEnum<'T>(Seq.append xseq other.Source) | |
| interface IAsyncEnumerable<'T> with | |
| member _.GetAsyncEnumerator(_) = AsyncIterator<'T>((xseq :> SeqItem<'T> seq).GetEnumerator()) | |
| //----- Async sequence definitons --------- | |
| type taskseq<'T> = IAsyncEnumerable<'T> | |
| type TaskSeqBuilder() = | |
| member _.Combine (first: AsyncEnum<'T>, second: AsyncEnum<'T>) = first.Combine(second) | |
| member _.Delay f = f() | |
| member _.For (xseq: 'T seq, f: 'T -> AsyncEnum<'b>) = AsyncEnum(xseq |> Seq.map (fun x -> Delayed <| fun () -> f x)) | |
| member _.Run(xseq: AsyncEnum<'T>) = xseq :> 'T taskseq | |
| member _.Yield (value: 'T) = AsyncEnum(Value value) | |
| member _.YieldFrom (task: Task<'T>) = AsyncEnum(TaskValue task) | |
| let taskseq = TaskSeqBuilder() | |
| // sample | |
| let grants: IdentityServer4.Models.Grant seq = [] | |
| let clients: IdentityServer4.Stores.IClientStore = null | |
| let modelList = taskseq { | |
| for grant in grants do | |
| yield! clients.FindClientByIdAsync(grant.ClientId) | |
| yield Client() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment