如何在Dream框架中根据路由参数提供文件?类型错误排查
Dream框架自定义路由处理函数类型不匹配问题解析
我尝试编写一个简单的Dream应用,通过路由参数关联对应的HTML文件处理路由,代码如下:
let serve_file dir request = Dream.from_filesystem dir ((Dream.param request "file") ^ ".html") let () = Dream.run @@ Dream.logger @@ Dream.router [ Dream.get "/" (Dream.from_filesystem "html" "index.html"); Dream.get "/:file" (serve_file "html") ]
运行时出现类型错误:
This expression has type Dream.request -> Dream.handler, but an expression was expected of
type: Dream.handler = Dream.request -> Dream.response Lwt.t
疑惑点:为什么第一个Dream.get能接受Dream.from_filesystem的调用结果,而自定义的serve_file不行?
问题根源
Dream.from_filesystem的类型为string -> string -> Dream.handler,其中Dream.handler的定义是Dream.request -> Dream.response Lwt.t,即接受请求并返回异步响应的函数。
- 第一个调用场景:
Dream.from_filesystem "html" "index.html"传入了目录和固定文件名,直接返回了一个Dream.handler类型的值,完全符合Dream.get对路由处理函数的要求。 - 自定义函数问题:
serve_file中Dream.from_filesystem dir ((Dream.param request "file") ^ ".html")这一行返回的是一个Dream.handler,但你直接将这个handler作为函数返回值,导致serve_file "html"的类型变成了Dream.request -> Dream.handler——也就是接受请求后再返回一个handler,而非直接返回异步响应,这与Dream.get要求的Dream.handler类型不匹配。
解决方法
只需调用返回的handler并传入当前请求request,让函数最终返回Dream.response Lwt.t类型的结果即可:
let serve_file dir request = (Dream.from_filesystem dir ((Dream.param request "file") ^ ".html")) request let () = Dream.run @@ Dream.logger @@ Dream.router [ Dream.get "/" (Dream.from_filesystem "html" "index.html"); Dream.get "/:file" (serve_file "html") ]
也可以用函数组合的方式简化写法:
let serve_file dir request = Dream.param request "file" |> (^) ".html" |> Dream.from_filesystem dir |> fun handler -> handler request let () = Dream.run @@ Dream.logger @@ Dream.router [ Dream.get "/" (Dream.from_filesystem "html" "index.html"); Dream.get "/:file" (serve_file "html") ]
修改后,serve_file "html"的类型将变为标准的Dream.handler,类型错误会消失。
内容的提问来源于stack exchange,提问作者Rawley Fowler
相关产品推荐
相关产品推荐

