7 people like it.

Coroutine

An implementation of Coroutine by using a continuation monad. It's using a monad library [1]. [1] https://github.com/fsharp/fsharpx

Coroutine

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
module Coroutine

// requires the monad library
open FSharp.Monad.Continuation
open System.Collections.Generic

type Coroutine<'T>() =
    let tasks = new Queue<Cont<'T,'T>>()
                
    member this.Put(task) =
        let withYield = 
            callCC <| fun exit ->
                task <| fun value -> 
                    callCC <| fun c -> 
                        tasks.Enqueue(c())
                        exit(value)
        tasks.Enqueue(withYield)

    member this.Run() =
        runCont (tasks.Dequeue()) id raise

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
let coroutine = Coroutine()

coroutine.Put(fun yield' -> cont {
    do! yield'(1)
    do! yield'(2)
    return 3
})

coroutine.Put(fun yield' -> cont {
    do! yield'(10)
    return 20
})

coroutine.Run() |> printfn "%A"
coroutine.Run() |> printfn "%A"
coroutine.Run() |> printfn "%A"
coroutine.Run() |> printfn "%A"
coroutine.Run() |> printfn "%A"
module Coroutine
namespace Microsoft.FSharp
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type Coroutine<'T> =
  new : unit -> Coroutine<'T>
  member Put : task:(('a -> 'b) -> 'c) -> 'd
  member Run : unit -> 'a

Full name: Coroutine.Coroutine<_>

--------------------
new : unit -> Coroutine<'T>
val tasks : obj
Multiple items
type Queue<'T> =
  new : unit -> Queue<'T> + 2 overloads
  member Clear : unit -> unit
  member Contains : item:'T -> bool
  member CopyTo : array:'T[] * arrayIndex:int -> unit
  member Count : int
  member Dequeue : unit -> 'T
  member Enqueue : item:'T -> unit
  member GetEnumerator : unit -> Enumerator<'T>
  member Peek : unit -> 'T
  member ToArray : unit -> 'T[]
  ...
  nested type Enumerator

Full name: System.Collections.Generic.Queue<_>

--------------------
Queue() : unit
Queue(capacity: int) : unit
Queue(collection: IEnumerable<'T>) : unit
val this : Coroutine<'T>
member Coroutine.Put : task:(('a -> 'b) -> 'c) -> 'd

Full name: Coroutine.Coroutine`1.Put
val task : (('a -> 'b) -> 'c)
val withYield : obj
val exit : ('a -> obj)
val value : 'a
val c : obj
member Coroutine.Run : unit -> 'a

Full name: Coroutine.Coroutine`1.Run
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
val raise : exn:System.Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
val coroutine : Coroutine<obj>

Full name: Coroutine.coroutine
member Coroutine.Put : task:(('a -> 'b) -> 'c) -> 'd
val yield' : (obj -> obj)
member Coroutine.Run : unit -> 'a
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/7M
Posted:13 years ago
Author:einblicker
Tags: continuations , coroutine