open System
// Replace with your type
type MyType<'a> = Async<'a>
type Internal<'a> = MyType<'a>
// Replace with types that feel similar and can be converted to `MyType`
type External1<'a> = System.Threading.Tasks.Task<'a>
type External2<'a> = System.Threading.Tasks.ValueTask<'a>
/// https://fsharpforfunandprofit.com/posts/computation-expressions-builder-part3/
type Delayed<'a> = unit -> MyType<'a>
// What is InlineIfLambda? This allows generation of high performance code which Computation Expressions have had in the past.
// See https://github.com/fsharp/fslang-design/blob/main/FSharp-6.0/FS-1098-inline-if-lambda.md
// We also mark everything an inline to try to squeeze as much performance out of the implementation as possible.
/// https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions#creating-a-new-type-of-computation-expression
type StubBuilder() =
/// Called for let! and do! in computation expressions.
member inline this.Bind(input: Internal<'T>, [] f: ('T -> Internal<'U>)) : Internal<'U> =
raise <| NotImplementedException()
/// Called for efficient let! and and! in computation expressions without merging inputs.
member inline this.Bind2
(
input: Internal<'T1>,
input2: Internal<'T2>,
[] f: ('T1 * 'T2 -> Internal<'U>)
) : Internal<'U> =
raise <| NotImplementedException()
/// Called for efficient let! and and! in computation expressions without merging inputs.
member inline this.Bind3
(
input: Internal<'T1>,
input2: Internal<'T2>,
input3: Internal<'T3>,
[] f: ('T1 * 'T2 * 'T3 -> Internal<'U>)
) : Internal<'U> =
raise <| NotImplementedException()
/// Called for return in computation expressions.
member inline this.Return(input: 'T) : Internal<'T> = raise <| NotImplementedException()
/// Called for return! in computation expressions.
member inline this.ReturnFrom(input: Internal<'T>) : Internal<'T> = input
/// Called for an efficient let! ... return in computation expressions.
member inline this.BindReturn(input: Internal<'T>, [] f: ('T -> 'U)) : Internal<'U> =
raise <| NotImplementedException()
/// Called for efficient let! ... and! ... return in computation expressions without merging inputs.
member inline this.Bind2Return
(
input: Internal<'T1>,
input2: Internal<'T2>,
[] f: ('T1 * 'T2 -> 'U)
) : Internal<'U> =
raise <| NotImplementedException()
/// Called for efficient let! ... and! ... return in computation expressions without merging inputs.
member inline this.Bind3Return
(
input: Internal<'T1>,
input2: Internal<'T2>,
input3: Internal<'T3>,
[] f: ('T1 * 'T2 * 'T3 -> 'U)
) : Internal<'U> =
raise <| NotImplementedException()
/// Called for and! in computation expressions.
member inline this.MergeSources(input: Internal<'T1>, input2: Internal<'T2>) : Internal<'T1 * 'T2> =
raise <| NotImplementedException()
/// Called for and! in computation expressions, but improves efficiency by reducing the number of tupling nodes.
member inline this.MergeSources3
(
input: Internal<'T1>,
input2: Internal<'T2>,
input3: Internal<'T3>
) : Internal<'T1 * 'T2 * 'T3> =
raise <| NotImplementedException()
/// Wraps a computation expression as a function. Delayed<'T> can be any type, commonly Internal<'T> or unit -> Internal<'T> are used.
/// Many functions use the result of Delay as an argument: Run, While, TryWith, TryFinally, and Combine
member inline this.Delay([] f: unit -> Internal<'T>) : Delayed<'T> =
raise <| NotImplementedException()
/// Executes a computation expression.
member inline this.Run([] f: Delayed<'T>) : Internal<'T> = raise <| NotImplementedException()
/// Called for sequencing in computation expressions.
member inline this.Combine(input: Internal<'T>, [] f: Delayed<'T>) : Internal<'T> =
raise <| NotImplementedException()
/// Called for sequencing in computation expressions.
member inline this.Combine(input: Internal, f: Internal<'T>) : Internal<'T> = raise <| NotImplementedException()
/// Called for while...do expressions in computation expressions.
member inline this.While
(
[] guard: unit -> bool,
[] body: Delayed<'T>
) : Internal<'T> =
raise <| NotImplementedException()
/// Called for while...do expressions in computation expressions.
member inline this.While
(
[] guard: unit -> bool,
[] body: Delayed
) : Internal =
raise <| NotImplementedException()
/// Called for for...do expressions in computation expressions.
member inline this.For(xs: #seq<'T>, [] f: 'T -> Internal<'U>) : Internal<'U> =
raise <| NotImplementedException()
/// Called for for...do expressions in computation expressions.
// Only need one of these For implementations
// member inline this.For(xs : #seq<'T>, [] f : 'T -> Internal<'U> ) : seq> =
// raise <| NotImplementedException()
/// Called for try...finally expressions in computation expressions.
member inline this.TryFinally
(
[] body: Delayed<'T>,
[] final: unit -> unit
) : Internal<'T> =
raise <| NotImplementedException()
/// Called for try...finally expressions in computation expressions.
member inline this.TryWith
(
[] body: Delayed<'T>,
[] failure: exn -> Internal<'T>
) : Internal<'T> =
raise <| NotImplementedException()
/// Called for use bindings in computation expressions.
member inline this.Using(resource: 'T when 'T :> IAsyncDisposable, [] f: 'T -> Internal<'U>) : Internal<'U> =
// This may not need to be implemented for non async-like CEs and can be replaced by the Using in the Extensions module
raise <| NotImplementedException()
/// Called for empty else branches of if...then expressions in computation expressions.
member inline _.Zero() : Internal<'a> = raise <| NotImplementedException()
/// Called to convert an External to Internal type before any others calls in computation expression.
/// This is the identity function for the internal type
member inline _.Source(identity: Internal<'a>) : Internal<'a> = identity
/// Called to convert an External to Internal type before any others calls in computation expression.
/// This is the identity function for for loops.
member inline _.Source(identity: #seq<'a>) : #seq<'a> = identity
/// Called to convert an External to Internal type before any others calls in computation expression.
member inline _.Source(other: External1