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

Haskell中Setter为何需要Traversable约束?

为什么Setter相关类型需要Traversable约束?

我研究了lens-family-core包中的setting函数,它的类型签名是:

setting :: Identical f => ((a -> b) -> s -> t) -> LensLike f s t a b

其中Identical类的定义是:

class (Traversable f, Applicative f) => Identical f

从setting的实现代码来看:

setting sec f = pure . sec (extract . f)

这里只用到了Applicative的pure和Identical的extract,所以我能理解这两个约束的必要性,但完全搞不懂为什么要加上Traversable约束。另外我发现lens包中的Setter也通过Settable约束间接包含了Traversable,看来这是Setter的普遍设计,想知道背后的原因。


核心原因:保障Setter行为合法性与体系兼容性

Traversable约束并不是直接为setting的当前实现服务,而是为了从类型层面保证Setter能遵循透镜体系的规则,同时和其他组件兼容:

  1. 强制执行Setter定律
    Setter必须满足两个关键定律才能保证行为可预测:
  • 恒等律:用id作为修改函数时,setter id必须等于id(修改后结构不变)
  • 组合律:setter (g . f)必须等于setter g . setter f(修改函数的组合对应Setter的组合)

Traversable配合Applicative能约束f这类函子的行为,避免有人定义出破坏这些定律的Identical/Settable实例。比如如果没有Traversable,可能会出现一个函子实例,它在“设置”过程中偷偷改变了原结构的形状,违反Setter的设计初衷。

  1. 与Traversal的体系兼容
    在透镜生态中,Setter是Traversal的特例——所有Traversal都可以用来设置值,而Setter是只专注于设置的简化版。Traversable是Traversal的核心约束之一,让Setter继承这个约束后,就能自然地和Traversal的操作(比如traverse)无缝配合,保持整个体系的一致性,不会出现接口割裂的情况。

  2. 设计层面的统一性
    lens系列库的设计围绕“遍历”这个核心概念展开,Setter作为其中的一部分,复用Traversable约束可以减少额外的类型类定义,同时让整个接口更统一。Settable(lens包)和Identical(lens-family-core)都继承Traversable,本质是让这类“设置专用”的函子符合遍历的基本要求,确保它们在整个透镜生态中能正确协作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 15:50:00