You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell Servant中serveWithContext的作用是什么?它能实现什么ReaderT做不到的功能?

Context与ReaderT的核心差异

两者根本不是同一层面的组件,作用域完全不重叠:

  • ReaderT是业务Handler层的依赖注入方案,仅对你自己编写的业务逻辑可见、可用。
  • Context是Servant框架层的依赖注入方案,专门给Servant内置的路由匹配、前置校验逻辑提供配置,这些逻辑运行在你自定义的Handler执行之前,完全感知不到你自己定义的ReaderT Monad栈,这就是ReaderT覆盖不到的场景。

比如你用的servant-auth组件的JWT校验、Cookie合法性校验,都是Servant在匹配到对应路由后,首先运行的框架内置逻辑,这时候你的ReaderT栈还没初始化,自然没法把配置通过ReaderT传给这些逻辑,必须通过Context传递。

你看到的"两次传参"不是重复,是用途完全不同

你给出的示例代码里的两次传参,分别对应两个不同的使用方:

-- 这部分是给框架层逻辑用的配置
cfg = defaultCookieSettings :. jwtCfg :. EmptyContext

上面塞进Context的配置,是给servant-auth的内置校验逻辑用的:比如校验请求带的JWT签名是否合法、Cookie是否在有效期内,都是用的Context里的这组配置。

-- 这部分是给你自己写的业务Handler用的配置
serveWithContext api cfg (server defaultCookieSettings jwtCfg)

这里手动传入server函数的配置,是给你自己编写的业务逻辑用的:比如你在checkCreds里需要手动生成JWT返回给客户端、手动给响应设置自定义Cookie,这时候用的就是你手动传的这组配置。

如果你的业务逻辑里不需要操作JWT、Cookie配置,完全可以不用手动传这部分参数,只保留Context里的配置即可,不存在强制重复传参的要求。

Context的设计逻辑

Context本质是类型安全的异构列表,Servant的内置逻辑可以根据需要的配置类型,自动从Context列表中查找对应的值,不需要使用者手动给框架逻辑传参,既保证了类型安全,又把框架层和业务层的配置注入完全隔离开,互不干扰。

内容的提问来源于stack exchange,提问作者Joshua Billson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:06:06