rspeele / TaskBuilder.fs

F# computation expression builder for System.Threading.Tasks
Creative Commons Zero v1.0 Universal
237 stars 27 forks source link

Non-generic Tasks #36

Closed kentcb closed 3 years ago

kentcb commented 3 years ago

Hello,

Thanks for this useful library.

What is the guidance for working with non-generic Tasks? A simple repro of my issue:

let doesThisWork : System.Threading.Tasks.Task =
    task {
        do! System.Threading.Tasks.Task.Delay(1000)
    }

Which produces this error:

FS0001    This expression was expected to have type
    'Threading.Tasks.Task'    
but here has type
    'Threading.Tasks.Task<unit>'

One workaround we have is:

type System.Threading.Tasks.Task with

    static member Ignore (task: Task<'T>) : Task =
        task :> Task

And then:

let doesThisWork : System.Threading.Tasks.Task =
    task {
        do! System.Threading.Tasks.Task.Delay(1000)
    } |> Task.Ignore

But this feels rather hacky.

gusty commented 3 years ago

It doesn't feel hacky to me. It feels explicit.

dsyme commented 3 years ago

Yes it feels pretty reasonable to me

isaacabraham commented 3 years ago

@kentcb This is pretty standard with generics when going from F# unit (as 'T) to void in C# where you have this "equivalent" type for the void case in C# but just a single type in F#.

gusty commented 3 years ago

Actually, F#+ has exactly that same Task.Ignore function, for the same purpose.

rspeele commented 3 years ago

Another option is the upcast operator. I find this nice when implementing interfaces that want a non-generic Task.

let doesThisWork : System.Threading.Tasks.Task =
    upcast task {
        do! System.Threading.Tasks.Task.Delay(1000)
    }
kentcb commented 3 years ago

Thanks all! Glad we're on the right track.