Skip to content

Instantly share code, notes, and snippets.

@ruxo
Last active February 9, 2023 23:13
Show Gist options
  • Select an option

  • Save ruxo/77ef3fa1e43235a64db1f5c3362093f2 to your computer and use it in GitHub Desktop.

Select an option

Save ruxo/77ef3fa1e43235a64db1f5c3362093f2 to your computer and use it in GitHub Desktop.
F# Task Sequence implementation attempt..
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