Seeking advice for creating CEs based on the new built in task
CE
#12792
Replies: 4 comments 2 replies
-
@mattfurness Just to say I'll take a look next week when back from vacation. To set expectations - with resumable code, in general we've been expecting people to define a new state machine type and use the existing resumable code builders, rather than reusing a different state machine type for a slightly adjusted purpose. However at first glance the approach you're using should, I believe, be a viable technique. I would expect the "Run" method to need to be inlined
Yes, this "While" function doesn't fit into the kind currently supported by Resumable.While. I'd expect this one to need fresh low-level resumable code. |
Beta Was this translation helpful? Give feedback.
-
@mattfurness As @dsyme said here #12217 "It's not a complicated thing and can be duplicated out as needed". That's what I did actually when I was playing with new task CE. I guess you might try using this (https://github.com/En3Tho/FSharpExtensions/blob/main/FSharpExtensions/En3Tho.FSharp.ComputationExpressions/TaskBuilders/ValueTaskResultBuilder.fs) builder as a reference. I can recommend maybe even copying task builder code from fsharp repo and trying to make your own from scratch. It's not hard once you got a proper base to build upon. Upd. Yep, this kind of while you mention is a problem - as @dsyme said, you would need a fresh resumable code for it. |
Beta Was this translation helpful? Give feedback.
-
Is it correct that |
Beta Was this translation helpful? Give feedback.
-
No |
Beta Was this translation helpful? Give feedback.
-
I am after some guidance on implementing computation expressions (CEs) that build upon the new built in task computation expression(s). The code can be found here. I will offer two examples and the hurdles that I ran into trying to implement them in the way i had envisaged. I had hoped that I would be able to implement the below CEs in a way that takes advantage of the performance characteristics and stacktrace benefits of the new task CEs. I know that I can use the
task
CE directly to implement them, but it is my understanding thattask.Run
would then be called for each function in the builder.The API
I thought it might be useful to summarize the TaskBuilder api here to make it easier to refer to, it is more complicated in reality but essentially boils down to:
Some relevant types for
TaskCode
are:Porting Expecto's
TestTaskBuilder
:The implementation that I was attempting to port can be found here. It is essentially a simple wrapper around a Task Builder, with some Expecto specific logic for
Run
. I started with the exact code linked to above (but with a dependency on the built intask {...}
and went from there:Issue 1: Compiler error
error FS3501: Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline'
Run
as inline. It is possible inlineRun
as well, ifname
andfocusState
are made available publicly.Run
as standard member (not inline), given it takes aTaskCode
as a parameter.Issue 2: Compiler error
error FS3511: This state machine is not statically compilable. The resumable code value(s) 'f' does not have a definition. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning.
task.Run
with theTaskCode
passed in always produces this warning, I could not find a way to get around it, the only way I could get it to compile was to suppress the error with#nowarn "3511"
Next I tried to annotate the
TestTaskBuilder
with types.TaskCode
in the type annotations.This construct is for use by compiled F# code and should not be used directly
.#nowarn "1204"
, but I was pretty surprised that using this type is so discouraged.Implementing a
TaskResultBuilder
:We have a
TaskResultBuilder
that depends onTaskBuilder.fs
. I wanted to port it over to depend on the new built inTaskBuilder
, it is quite similar to the one provided in FsToolkit.ErrorHandling which depends on Ply and it's intermediatryPly<'u>
type anduply
CE, so I will link to it for additional context.The
TaskResult
type:Bind
I had hoped to create a
Bind
function with the signature, similar to thisTaskCode<Result<'TOverall, 'Error>, Result<'TResult2, 'Error>>
when the result is an error:While
I had hoped to create a
While
function with the signature, similar to this:bool
back that is related to the resumable code flow:I'm not sure the best way to resolve the two issues above, but I am hoping to utilize
TaskBuilder
and not have to write the low level resumable code myself. I know that when creating aTaskCode
you provide a function that has aTaskStateMachineData
parameter, however theResult
property of that type restricts the'TOverall
type parameter not the'T
type parameterGeneral questions:
Any advice or insight would be greatly appreciated. If there is a more appropriate place to ask/post this question let me know and I will do so.
Beta Was this translation helpful? Give feedback.
All reactions