optics-java 是一个独立的 Java 光学、HKT、类型代数和优化器实验库。当前重点是把 DataFixerUpper(以下简称 DFU)里和类型重写、无点式优化、递归类型处理等相关的理论部分,用更适合 OELib 的方式重新实现。
本项目全程由人工指导,代码由 GPT-5.5 编写。
本项目基于 DataFixerUpper 的 HKT、光学、无点式重写、类型重写和递归类型重写相关部分做了本地重写。这里并没有完全复刻 DFU,而是抽取其中的理论内核,用作配置库底层。
本项目已经解决了若干 DFU 已知问题:
- 积类型、和类型、标签选择分支排序后的类型修复 DFU / Issue#108。
- 递归重写中的分支/索引裁剪。
- 递归 cata/fold 融合的显式依赖证据。
- ReflexCata 的相等性判断问题,改为显式恒等代数证据。
- 字段/类型查找统一路径。
- 递归点的模板贯穿和 μ 边界修复。
在 DFU 已有思想之外,本项目主要补上了这些理论实现:
- Java 侧结构化类型代数,把记录、标签选择、密封子类型、递归族槽位等项目需要的类型结构纳入优化器可检查的数据。
- 四参数带类型光学脊柱:
S -> T、A -> B分离,优化器可以在重写后修复光学元数据。 - fold/query IR,用于 fold-map 融合、积式 fold 融合、preview、first、any、all、count 等查询优化。
- 通用递归特化,把结构化通用递归函数降到
CataPlan。 - 证据驱动的 ReflexCata,只有显式自反恒等证据和依赖证据足够时才消成恒等函数。
在真实应用型迁移基准中,本项目与 DFU 基本持平。把优化器场景单独拆出来看,两边仍会出现差异,整体属于平分秋色:有 DFU 更高的地方,也有本项目更高的地方。
本项目在优化器里保留了更严格的理论检查,因此部分单独拆出的优化器场景可能因为这些检查而不如 DFU,但真实开发中这类差异影响微乎其微。
基础 HKT 编码使用 K1、K2、App、App2、Kind1、Kind2 表示一元和二元类型构造子应用。当前包含的类型类和能力接口主要有:
FunctorApplicativeSelectiveMonadContravariantBifunctorNaturalSemigroupMonoidFoldableTraversableProfunctorCartesianStrongCocartesianChoiceClosedTraversingMappingAffinePMonoidalMonoidProfunctorFunctorProfunctorReCartesianReCocartesian
核心 profunctor carrier 和辅助结构包括:
FunctionArrowForgetForgetEForgetOptReForgetReForgetCReForgetEReForgetPReForgetEPProcomposeConstGrateWander
核心数据类型包括:
Maybe<A>Either<L, R>Try<A>Validated<E, A>Tuple2<A, B>Pair<A, B>IdF<A>Unit
核心光学 API 包括:
Iso<S, A>Lens<S, A>Prism<S, A>Affine<S, A>Traversal<S, A>Fold<S, A>Getter<S, A>Setter<S, A>Optic<S, T, A, B>
带索引光学包括:
IndexedOptic<I, S, A>IndexedLens<I, S, A>IndexedTraversal<I, S, A>IndexedFold<I, S, A>
常用实例和工具包括:
EachInstancesIxedInstancesAtInstancesTraversalsPrismsAffinesOptionalsListPrismsListTraversalsStringTraversalsEitherTraversalsTryTraversalsValidatedTraversalsTupleTraversals
com.flechazo.optics.focus 提供轻量焦点 DSL,用于把生成出的焦点路径继续组合到 lens、traversal、affine 等光学结构。
优化器是一个分层构造的等式重写系统,只在结构信息和类型证据足够时改写表达式,本质是 IR + 一个小型优化编译器。
底层是带类型的无点式 IR,将光学操作拆解为组合子树(组合、应用、恒等、bang、Fn、opticApp、cataPlan 等),使表达式可代数操作。中层是策略式重写引擎,用 topDown、bottomUp、once、many、all、one 等组合子将遍历策略与变换规则解耦。上层是四参数类型化光学脊柱,将光学表示为可检查、可比较、可前缀提取/后缀切分的带类型元素序列——每条光学是一条 profunctor 变换 P A B → P S T。
参考:
Optimizing functions:
- Cunha, A., & Pinto, J. S. (2005). Point-free program transformation
- Lämmel, R., Visser, E., & Visser, J. (2002). The essence of strategic programming
How to handle recursive types:
- Cunha, A., & Pacheco, H. (2011). Algebraic specialization of generic functions for recursive types
- Yakushev, A. R., Holdermans, S., Löh, A., & Jeuring, J. (2009, August). Generic programming with fixed points for mutually recursive datatypes
- Magalhães, J. P., & Löh, A. (2012). A formal comparison of approaches to datatype-generic programming
Optics:
- Pickering, M., Gibbons, J., & Wu, N. (2017). Profunctor Optics: Modular Data Accessors
- Pacheco, H., & Cunha, A. (2010, June). Generic point-free lenses
Tying it together:
- Cunha, A., Oliveira, J. N., & Visser, J. (2006, August). Type-safe two-level data transformation
- Cunha, A., & Visser, J. (2011). Transformation of structure-shy programs with application to XPath queries and strategic functions
- Pacheco, H., & Cunha, A. (2011, January). Calculating with lenses: optimising bidirectional transformations
本项目使用 Class File API 生成隐藏类执行器。字节码后端会先运行标准优化器,再为支持的无点式计划生成专用执行器/函数类;不支持的节点保留解释执行兜底路径。
本项目基于 Java 21 构建。
主要依赖:
io.smallrye.classfile:jdk-classfile-backport