I have this code:
Ok stringBuffer {
let r = get some list....
match r with
| [] -> "no active tasks"
| r -> String.Join("\n", r)
}
with stringBuffer defined as:
[<AutoOpen>]
module StringBuffer =
type StringBuffer = StringBuilder -> unit
type StringBufferBuilder () =
member inline this.Yield (txt: string) = fun (b: StringBuilder) -> Printf.bprintf b "%s" txt
member inline this.Yield (c: char) = fun (b: StringBuilder) -> Printf.bprintf b "%c" c
member inline this.Yield (strings: #seq<string>) = fun (b: StringBuilder) -> for s in strings do Printf.bprintf b "%s\n" s
member inline this.YieldFrom (f: StringBuffer) = f
member this.Combine (f, g) = fun (b: StringBuilder) -> f b; g b
member this.Delay f = fun (b: StringBuilder) -> (f()) b
member this.Zero () = ignore
member this.For (xs: 'a seq, f: 'a -> StringBuffer) =
fun (b: StringBuilder) ->
use e = xs.GetEnumerator ()
while e.MoveNext() do
(f e.Current) b
member this.While (p: unit -> bool, f: StringBuffer) =
fun (b: StringBuilder) -> while p () do f b
member this.Run (f: StringBuffer) =
let b = StringBuilder()
do f b
b.ToString()
let stringBuffer = StringBufferBuilder()
type StringBufferBuilder with
member inline this.Yield (b: byte) = fun (sb: StringBuilder) -> Printf.bprintf sb "%02x " b
I am not the author of the StringBuffer module. I'm using it regularly as it makes using StringBuilder super convenient to use in F#
I can mix strings and logic easily:
stringBuffer {
"hello"
if x = 3 then "world"
}
but, in the example at the beginning of this post, I am getting the following compilation error:
[FS0708] This control construct may only be used if the computation expression builder defines a 'Zero' method.
In the computation expression, the Zero method is defined as ignore so the problem is probably there. But my question is:
What is this error about? why does this specific use case require the implementation of the Zero method?
My understanding is that the Zero method is used if the expression would return nothing, as it is not valid for a computation expression; But since I specify a string, why would this execution path return nothing?
Edit:
Screenshot of the error (Rider / dotnet 5)
Now, the error is reduced to this scenario:
Ok stringBuffer {
let r = get some list....
match r with
| [] -> "no active tasks"
| r -> String.Join("\n", r)
}
trigger the error, but
let s =
stringBuffer {
let r = get some list....
match r with
| [] -> "no active tasks"
| r -> String.Join("\n", r)
}
Ok s
does not