我已经开始学习F#和Suave了,我正在读F#应用一书。
我正在挣扎的一件事是warbler函数。我知道这与推迟执行有关,但我不太明白为什么和何时需要执行。
显然,我们还可以使用request函数作为warbler的替代方案。
有谁能提供更多关于为什么和何时使用这些函数的详细信息吗?
发布于 2016-11-12 10:46:40
这三个函数是相关的,因为request和context是warbler的专门版本。他们都做同样的事情-他们检查(某一方面)他们的论点,并给你一个函数,以适用于该论点。
请记住,Suave的基本“构建块”WebPart是一个函数HttpContext -> Async<HttpContext option>,而不是一些具体的对象。这实际上意味着,这三个函数允许您检查这个HttpContext,并在此基础上组成一个要使用的WebPart。
在其核心,warbler所做的非常简单:
let warbler f a = f a a
// ('t -> 't -> 'u) -> 't -> 'u给它一个函数f和参数a。函数f查看a并返回一个新的函数't -> 'u,然后应用于a。
关于warbler,它是完全通用的--只要类型对齐,就可以在任何地方使用context或request,但是它不知道Suave感兴趣的域。
这就是为什么有专门版本的“讲域语言”:
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类型是“硬编码”--这使得使用起来更加方便。
发布于 2016-11-12 11:13:16
另一个答案已经解释了warbler函数及其与context和request函数的关系。我想展示一下你想什么时候使用这些。
启动Suave服务器时,需要为其提供WebParts路由、HTTP方法和响应生成函数的请求处理管道。这意味着,当您启动web服务器时,已经评估了提供给部分应用的WebPart函数的所有参数。
假设有一个极简的web应用程序打印当前服务器时间:
let app = GET >=> path "/" >=> OK (string DateTime.Now)如果您使用此app管道启动web服务器,则始终会看到在创建app值时生成的时间戳,无论何时发出检索它的web请求。
warbler函数及其专用版本context和request不仅推迟了执行,而且使web服务器能够在每次需要其结果时调用所提供的函数。
在示例场景中,此app将提供预期的结果:
let app = GET >=> path "/" >=> warbler (fun ctx -> OK (string DateTime.Now))@adzdavies的评论显示了一种不一定需要warbler的替代方法。在本例中,如果使用匿名函数语法而不是部分应用OK,也可以推迟参数评估。
let app = GET >=> path "/" >=> (fun ctx -> OK (string DateTime.Now) ctx)发布于 2020-12-09 18:50:08
我发现先前的解释(对我来说)令人费解。这是我试图澄清..。
warbler解决了一个优化的、不纯的、急切的、评估功能语言的问题,其中部分应用的参数被早期评估并缓存。当这些应用的参数依赖于副作用,并且每次调用都需要有新的值时,这种缓存就会出现问题。例如,对当前系统时间的string表示形式的以下查询将发生,并在g: string -> string的定义处缓存。因此,它将为每次对g的调用返回相同的值。
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函数,如下所示:
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的初衷。
let warbler f x = (f x) x应该注意的是,要重新评估工作,f必须是调用点上的匿名函数。因此,似乎不再有任何实用的warbler概念,酷的名称可能应该被废弃,并允许重新出现一些其他有用的概念。
顺便说一句,我与warbler的相遇是与Giraffe。
https://stackoverflow.com/questions/40561394
复制相似问题