首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >F# Suave莺函数

F# Suave莺函数
EN

Stack Overflow用户
提问于 2016-11-12 09:21:31
回答 3查看 1.4K关注 0票数 20

我已经开始学习F#和Suave了,我正在读F#应用一书。

我正在挣扎的一件事是warbler函数。我知道这与推迟执行有关,但我不太明白为什么和何时需要执行。

显然,我们还可以使用request函数作为warbler的替代方案。

有谁能提供更多关于为什么和何时使用这些函数的详细信息吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-12 10:46:40

这三个函数是相关的,因为requestcontextwarbler的专门版本。他们都做同样的事情-他们检查(某一方面)他们的论点,并给你一个函数,以适用于该论点。

请记住,Suave的基本“构建块”WebPart是一个函数HttpContext -> Async<HttpContext option>,而不是一些具体的对象。这实际上意味着,这三个函数允许您检查这个HttpContext,并在此基础上组成一个要使用的WebPart

在其核心,warbler所做的非常简单:

代码语言:javascript
复制
let warbler f a = f a a  
// ('t -> 't -> 'u) -> 't -> 'u

给它一个函数f和参数a。函数f查看a并返回一个新的函数't -> 'u,然后应用于a

关于warbler,它是完全通用的--只要类型对齐,就可以在任何地方使用contextrequest,但是它不知道Suave感兴趣的域。

这就是为什么有专门版本的“讲域语言”:

代码语言:javascript
复制
let request apply (a : HttpContext) = apply a.request a
// (HttpRequest -> HttpContext -> 'a) -> HttpContext -> 'a 
let context apply (a : HttpContext) = apply a a
// (HttpContext -> HttpContext -> 'a) -> HttpContext -> 'a 

请注意,它们与莺具有相同的“形状”--唯一的区别是HttpContext类型是“硬编码”--这使得使用起来更加方便。

票数 20
EN

Stack Overflow用户

发布于 2016-11-12 11:13:16

另一个答案已经解释了warbler函数及其与contextrequest函数的关系。我想展示一下你想什么时候使用这些。

启动Suave服务器时,需要为其提供WebParts路由、HTTP方法和响应生成函数的请求处理管道。这意味着,当您启动web服务器时,已经评估了提供给部分应用的WebPart函数的所有参数。

假设有一个极简的web应用程序打印当前服务器时间:

代码语言:javascript
复制
let app = GET >=> path "/" >=> OK (string DateTime.Now)

如果您使用此app管道启动web服务器,则始终会看到在创建app值时生成的时间戳,无论何时发出检索它的web请求。

warbler函数及其专用版本contextrequest不仅推迟了执行,而且使web服务器能够在每次需要其结果时调用所提供的函数。

在示例场景中,此app将提供预期的结果:

代码语言:javascript
复制
let app = GET >=> path "/" >=> warbler (fun ctx -> OK (string DateTime.Now))

@adzdavies的评论显示了一种不一定需要warbler的替代方法。在本例中,如果使用匿名函数语法而不是部分应用OK,也可以推迟参数评估。

代码语言:javascript
复制
let app = GET >=> path "/" >=> (fun ctx -> OK (string DateTime.Now) ctx)
票数 32
EN

Stack Overflow用户

发布于 2020-12-09 18:50:08

我发现先前的解释(对我来说)令人费解。这是我试图澄清..。

warbler解决了一个优化的、不纯的、急切的、评估功能语言的问题,其中部分应用的参数被早期评估并缓存。当这些应用的参数依赖于副作用,并且每次调用都需要有新的值时,这种缓存就会出现问题。例如,对当前系统时间的string表示形式的以下查询将发生,并在g: string -> string的定义处缓存。因此,它将为每次对g的调用返回相同的值。

代码语言:javascript
复制
let g = sprintf "%s %s" (string DateTime.Now)

g "a"  //"12/09/2020 18:33:32 a"
g "b"  //"12/09/2020 18:33:32 b"

但是,没有必要使用warbler概念来解决这个重新评估问题。只要简单地将subject函数封装在一个匿名函数中就足够了,然后每次都完全应用subject函数,如下所示:

代码语言:javascript
复制
let f = (fun x -> sprintf "%s %s" (string DateTime.Now) x)

f "c"    //"12/09/2020 18:53:32 c"
f "d"    //"12/09/2020 18:53:34 d"

相反,warbler所做的是使用上面的匿名函数作为函数工厂,在调用时生成subject函数。然后用第二个参数调用主语函数。warbler使用其第二个参数调用工厂函数是偶然的,但它确实存在一个误导点。可以想象,将参数传递给工厂可以允许工厂配置subject函数或选择替代类型兼容函数返回到warbler。尽管如此,这并不是warbler的初衷。

代码语言:javascript
复制
let warbler f x = (f x) x

应该注意的是,要重新评估工作,f必须是调用点上的匿名函数。因此,似乎不再有任何实用的warbler概念,酷的名称可能应该被废弃,并允许重新出现一些其他有用的概念。

顺便说一句,我与warbler的相遇是与Giraffe

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40561394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档