【发布时间】:2012-02-09 20:47:11
【问题描述】:
我找到了这个 sn-p:
但我不仅使用可重试函数,还使用异步函数,我想知道如何正确地制作这种类型。我有一小块 retryAsync monad 我想用它来代替异步计算,但它包含重试逻辑,我想知道如何组合它们?
type AsyncRetryBuilder(retries) =
member x.Return a = a // Enable 'return'
member x.ReturnFrom a = x.Run a
member x.Delay f = f // Gets wrapped body and returns it (as it is)
// so that the body is passed to 'Run'
member x.Bind expr f = async {
let! tmp = expr
return tmp
}
member x.Zero = failwith "Zero"
member x.Run (f : unit -> Async<_>) : _ =
let rec loop = function
| 0, Some(ex) -> raise ex
| n, _ ->
try
async { let! v = f()
return v }
with ex -> loop (n-1, Some(ex))
loop(retries, None)
let asyncRetry = AsyncRetryBuilder(4)
消费代码是这样的:
module Queue =
let desc (nm : NamespaceManager) name = asyncRetry {
let! exists = Async.FromBeginEnd(name, nm.BeginQueueExists, nm.EndQueueExists)
let beginCreate = nm.BeginCreateQueue : string * AsyncCallback * obj -> IAsyncResult
return! if exists then Async.FromBeginEnd(name, nm.BeginGetQueue, nm.EndGetQueue)
else Async.FromBeginEnd(name, beginCreate, nm.EndCreateQueue)
}
let recv (client : MessageReceiver) timeout =
let bRecv = client.BeginReceive : TimeSpan * AsyncCallback * obj -> IAsyncResult
asyncRetry {
let! res = Async.FromBeginEnd(timeout, bRecv, client.EndReceive)
return res }
错误是:
此表达式的类型应为
Async<'a>,但这里的类型为 'b ->Async<'c>
【问题讨论】:
-
哪里出现错误(行)?
-
关于具体错误,你的
Bind应该将参数作为一个元组(写x.Bind(expr, f)而不是x.Bind expr f)。这大概就是原因。但是,它也根本不使用f,这是非常可疑的(并且您的Return类型错误)。
标签: asynchronous f#