【问题标题】:why can't I use do! when I want to ignore the result, in F#为什么我不能用do!当我想忽略结果时,在 F#
【发布时间】:2021-10-20 18:53:24
【问题描述】:

在以下代码中:

let! _ = 
    connection
    |> Sql.existingConnection
    |> Sql.query $"LISTEN \"{accountId}.{notificationName}\""
    |> Sql.executeNonQueryAsync

我忽略了结果,我认为我可以用 do! 语句替换它,但是:

do! 
    connection
    |> Sql.existingConnection
    |> Sql.query $"LISTEN \"{accountId}.{notificationName}\""
    |> Sql.executeNonQueryAsync

不会编译:

这个表达式应该有类型'int',但这里有类型'unit'

并在末尾添加 |>ignore 并不能解决问题。这样做的正确方法是什么?


编辑:

这里是完整的代码:

// start a loop, waiting for events
async {
    try
        // create a connection
        use connection = getConnection location

        // add the callback
        connection.Notification.Add (fun x -> callback (JObject.Parse x.Payload).["data"])

        // listen to the notifications
        let! _ =
            connection
            |> Sql.existingConnection
            |> Sql.query $"LISTEN \"{accountId}.{notificationName}\""
            |> Sql.executeNonQueryAsync

        // loop for events
        while true do
            try
                do! connection.WaitAsync()
            with ex ->
                error ex.Message
                Thread.Sleep(TimeSpan.FromSeconds(2.))
    with ex ->
        failwith $"{ex.Message}"
}
|> Async.StartAsTask
|> ignore

问题函数 (Sql.executeNonQueryAsync) 来自此库:https://github.com/Zaid-Ajaj/Npgsql.FSharp/blob/50d3409fec844526e3c44901d64c8361b09e42a3/src/Npgsql.FSharp.fs(它是该文件的最后一个函数)

该库是围绕 Postgres 的 SQL 客户端的 F# 包装器。

【问题讨论】:

  • 你试过Async.Ignore吗?
  • 是的,它给了我错误:无法根据此程序点之前的类型信息确定方法“源”的唯一重载。可能需要类型注释。
  • 很难说。我不知道这些类型是什么,所以它只是在黑暗中拍摄,没有可重现的东西。
  • @PhillipCarter,最后一次调用返回一个Task;但是,是的,这对我来说似乎很奇怪。
  • 如果你想得到这个答案,你需要指定 Sql 模块是什么(一些库?),你到底在哪里得到错误(哪一行?)以及什么是您正在使用的计算表达式生成器(任务还是异步?)没有这个,就不可能知道...

标签: f#


【解决方案1】:

您需要使用:> 运算符将Task<'T> 转换为Task

do! 
    connection
    |> Sql.existingConnection
    |> Sql.query $"LISTEN \"{accountId}.{notificationName}\""
    |> Sql.executeNonQueryAsync
    :> Task

您也可以使用以下扩展名使其与Async.Ignore 保持一致

open System.Threading.Tasks
type Task with
    static member Ignore (t: Task<'T>) =
        t :> Task

这样就变成了

do! 
    connection
    |> Sql.existingConnection
    |> Sql.query $"LISTEN \"{accountId}.{notificationName}\""
    |> Sql.executeNonQueryAsync
    |> Task.Ignore

【讨论】:

  • using :> 任务也将无法编译:无法根据此程序点之前的类型信息确定方法“源”的唯一重载。可能需要类型注释。
  • Source 没有出现在您的代码中的任何位置,所以看起来该错误可能是一个单独的问题?
  • 有些东西没有加起来,只是意识到您的代码 sn-p 使用 async 计算表达式,但有问题的库返回 Task&lt;'T&gt; 所以没有办法使用 let! _ 的原始代码在没有第一次管道到Async.AwaitTask 的情况下工作尝试在解决方案的末尾添加|&gt; Async.AwaitTask
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
  • 2021-12-21
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 2020-06-18
  • 2020-11-08
相关资源
最近更新 更多