异步方法中的类型不匹配
Type mismatch in async method
我正在编写一个异步方法,它应该异步查询一个端口,直到它找到一个端口,或者在 5 分钟时超时;
member this.GetPort(): Async<Port> = this._GetPort(DateTime.Now)
member this._GetPort(startTime: DateTime): Async<Port> = async {
match this._TryGetOpenPort() with
| Some(port) -> port
| None -> do
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
else
do! Async.Sleep(100)
let! result = this._GetPort(startTime)
result}
member this._TryGetOpenPort(): Option<Port> =
// etc.
但是,我在 _GetPort
中遇到了一些奇怪的类型不一致问题;该函数说我正在返回一种 Async<unit>
而不是 Async<Port>
.
这有点不直观,但让您的代码正常工作的方法是这样的:
member private this.GetPort(startTime: DateTime) =
async {
match this.TryGetOpenPort() with
| Some port ->
return port
| None ->
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
do! Async.Sleep(100)
let! result = this.GetPort(startTime)
return result
}
member private this.TryGetOpenPort() = failwith "yeet" // TODO
我冒昧地清理了一些东西并将成员设为私有,因为这似乎是您在这里主要追求的目标,并提供更详细的内部方法来获取端口。
您的代码未编译的原因是您在计算中 return
的内容不一致:
- 在
Some(port)
的情况下,您缺少 return
关键字 - 需要将值提升回 Async<port>
- 你引发异常的
if
表达式有一个 else
分支,但你不是 return
从这两个分支。在这种情况下,由于您显然不希望 return 任何东西而只是引发异常,因此您可以省略 else
并使其成为命令式程序流,就像在非异步代码中一样。
您可能希望考虑的另一件事是抛出异常是否是您想要的,或者只是 return 一个 Result<T,Err>
或一个选项是否是正确的调用。异常本身并不是坏事,但如果有一种很好的方法可以将含义归因于包装您的 return 值的类型,那么很多 F# 编程通常会导致避免使用它们。
我正在编写一个异步方法,它应该异步查询一个端口,直到它找到一个端口,或者在 5 分钟时超时;
member this.GetPort(): Async<Port> = this._GetPort(DateTime.Now)
member this._GetPort(startTime: DateTime): Async<Port> = async {
match this._TryGetOpenPort() with
| Some(port) -> port
| None -> do
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
else
do! Async.Sleep(100)
let! result = this._GetPort(startTime)
result}
member this._TryGetOpenPort(): Option<Port> =
// etc.
但是,我在 _GetPort
中遇到了一些奇怪的类型不一致问题;该函数说我正在返回一种 Async<unit>
而不是 Async<Port>
.
这有点不直观,但让您的代码正常工作的方法是这样的:
member private this.GetPort(startTime: DateTime) =
async {
match this.TryGetOpenPort() with
| Some port ->
return port
| None ->
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
do! Async.Sleep(100)
let! result = this.GetPort(startTime)
return result
}
member private this.TryGetOpenPort() = failwith "yeet" // TODO
我冒昧地清理了一些东西并将成员设为私有,因为这似乎是您在这里主要追求的目标,并提供更详细的内部方法来获取端口。
您的代码未编译的原因是您在计算中 return
的内容不一致:
- 在
Some(port)
的情况下,您缺少return
关键字 - 需要将值提升回Async<port>
- 你引发异常的
if
表达式有一个else
分支,但你不是return
从这两个分支。在这种情况下,由于您显然不希望 return 任何东西而只是引发异常,因此您可以省略else
并使其成为命令式程序流,就像在非异步代码中一样。
您可能希望考虑的另一件事是抛出异常是否是您想要的,或者只是 return 一个 Result<T,Err>
或一个选项是否是正确的调用。异常本身并不是坏事,但如果有一种很好的方法可以将含义归因于包装您的 return 值的类型,那么很多 F# 编程通常会导致避免使用它们。