F# - 将 Task<unit> 转换为普通 Task

F# - Convert Task<unit> to plain Task

我正在使用 Giraffe 通过异步工作流创建本机 .NET 任务,因为我需要与 Discord.NET 库的互操作性。我有一个需要 Task 的事件,但是我正在编写 returns 一个 Task<unit> 的事件处理程序,并且由于某种原因,类型检查器不够聪明,无法意识到这一点这是同一件事。有没有办法将 Task<unit> 转换为直线 Task

这是我的代码:

let messageReceived (msg : SocketMessage) =
    task {
        let author = msg.Author.Username
        let text = msg.Content
        match msg.Author.Username with
            | "Monika" -> ()
            | usr ->
                if text.ToLower().StartsWith "<@407367655830585344> say" then
                    text.Substring 26 |> msg.Channel.SendMessageAsync |> ignore
                else if text.ToLower().StartsWith "<@407367655830585344>" then
                    let response = (Lines.VoiceLines |> Extras.randomElement).Replace("[player]", author)
                    msg.Channel.SendMessageAsync response |> ignore
                else if text.ToLower().StartsWith "delete" then
                    text.Substring 7 + ".chr deleted" |> msg.Channel.SendMessageAsync |> ignore
                else if Extras.onein 10 then
                    let response = (Lines.VoiceLines |> Extras.randomElement).Replace("[player]", author)
                    msg.Channel.SendMessageAsync response |> ignore
    }

_client.add_MessageReceived (fun m -> messageReceived m)

最后一行产生一个错误,说 MessageReceived 事件需要一个签名为 SocketMessage -> Task:

的函数

error FS0001: This expression was expected to have type 'Task' but here has type 'Task<unit>'

TaskTask<T> 的基础 class,因此您应该可以使用 :> 运算符将 Task<unit> 向上转换为 Task .尝试这样的事情:

(fun m -> messageReceived m :> Task)

我认为这个最小的例子重现了这个问题:

// int -> Task<unit>
let sleepTaskT (m : int) = Async.Sleep m |> Async.StartAsTask
// (int -> Task) -> Task
let foo (f : int -> Task) = f 1000
// "This expression was expected to have type 'Task' but here has type 'Task<unit>'"
foo (fun m -> sleepTaskT m)
// this works by explicitly upcasting sleepTaskT's Task<unit> to Task
foo (fun m -> sleepTaskT m :> Task)