Skip to content

Functions for working with AsyncSeq and Channel #170

Description

@njlr

I propose adding two functions:

AsyncSeq.toChannel : ChannelWriter<'a> -> AsyncSeq<'a> -> Async<unit>

AsyncSeq.fromChannel : ChannelReader<'a> -> AsyncSeq<'a>

AsyncSeq.toChannel would be used to fill a ChannelWriter from an AsyncSeq

AsyncSeq.fromChannel would be used to empty a ChannelReader into an AsyncSeq

Here is an initial implementation:

#r "nuget: FSharp.Control.AsyncSeq, 2.0.23"

open System.Threading.Channels
open FSharp.Control

[<RequireQualifiedAccess>]
module AsyncSeq =

  let toChannel (writer : ChannelWriter<'a>) (xs :  AsyncSeq<'a>) : Async<unit> =
    async {
      try
        for x in xs do
          if not (writer.TryWrite(x)) then
            let! ct = Async.CancellationToken

            do!
              writer.WriteAsync(x, ct).AsTask()
              |> Async.AwaitTask

        writer.Complete()
      with exn ->
        writer.Complete(error = exn)
    }

  let fromChannel (reader : ChannelReader<'a>) : AsyncSeq<'a> =
    asyncSeq {
      let mutable keepGoing = true

      while keepGoing do
        let mutable item = Unchecked.defaultof<'a>

        if reader.TryRead(&item) then
          yield item
        else
          let! ct = Async.CancellationToken

          let! hasMoreData =
            reader.WaitToReadAsync(ct).AsTask()
            |> Async.AwaitTask

          if not hasMoreData then
            keepGoing <- false
    }
// Demo
async {
  let xs = [ 0 .. 9] |> AsyncSeq.ofSeq

  let channel = Channel.CreateBounded(4)

  do!
    Async.Parallel
      [|
        AsyncSeq.toChannel channel.Writer xs

        async {
          for x in AsyncSeq.fromChannel channel.Reader do
            printfn $"%i{x}"
        }
      |]
    |> Async.Ignore<unit array>
}
|> Async.RunSynchronously

Would a PR be accepted?

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions