我刚开始阅读 Tamizhvendan S 的书F# Applied并遇到了以下代码片段:
type WebPart = Context -> Async<Context option>
我一直在浏览 Microsoft 的 F# 文档以及我最喜欢的 F# 站点 Scott Wlaschin 的站点,F# for Fun and Profit
但找不到对这种类型的任何引用。它似乎不像记录类型。它几乎看起来像是一个普通的旧功能。那是什么?
感谢您的帮助。
您正在查看的WebPart
类型来自Suave。您可以在https://suave.io/async.html阅读更多相关信息,但我会总结一下。你是对的:它是一个函数的类型。具体来说,它是一个接受 a Context
(在 Suave 中是 HTTP 请求记录和响应记录的组合)并Context option
异步返回 a 的函数。也就是说,由于某些请求可能会失败,因此该函数可以选择返回None
而不是返回值。由于某些请求可能需要很长时间,因此所有请求都被视为异步返回,因此Async
.
为了将两个请求链接在一起,Suave 提供了绑定运算符>=>
,这样您就不必一直通过键入样板async { match result1 with None -> None | Some x -> return! request2 x
;相反,您可以输入request1 >=> request2
相同的效果。
如果您需要更多帮助并且通读 Suave 文档并没有提供您需要的帮助,请告诉我们,我们将尝试进一步解释。
这太长了,不能发表评论。而且我从来没有使用过Suave。但是,我认为我可以从所涉及类型的一元属性中猜到>=>
不是绑定运算符,而是 Kleisli 组合运算符。在不遵守单子定律或试图理解范畴论的情况下,只需假设签名为:
val ( >>= ) : Async<'a option> -> ('a -> Async<'b option>) -> Async<'b option> val ( >=> ) : ('a -> Async<'b option>) -> ('b -> Async<'c option>) -> 'a -> Async<'c option>
绑定运算符接受 anAsync<'a option>
并通过绑定函数'a -> Async<'b option>
将其转换为Async<'b option>
. Kleisli 运算符将两个绑定函数组合成第三个。
这些运算符正在处理比类型缩写描述的具体类型更通用的一元类型和函数type WebPart = Context -> Async<Context option>
。运算符的实现几乎是自然而然的。
let (>>=) request1 binder = async {
let! result1 = request1
match result1 with
| None -> return None
| Some x -> return! binder x }
let (>=>) f g a = f a >>= g