optics-java 是一个独立的 Java 光学、HKT、类型代数和优化器实验库。当前重点是把 DataFixerUpper(以下简称 DFU)里和类型重写、无点式优化、递归类型处理等相关的理论部分,用更适合 OELib 的方式重新实现。
本项目基于 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,只有显式自反恒等证据和依赖证据足够时才消成恒等函数。
优化器是一个分层构造的等式重写系统,只在结构信息和类型证据足够时改写表达式,本质是 IR + 一个小型优化编译器。
底层是带类型的无点式 IR,将光学操作拆解为组合子树(组合、应用、恒等、bang、Fn、opticApp、cataPlan 等),使表达式可代数操作。中层是策略式重写引擎,用 topDown、bottomUp、once、many、all、one 等组合子将遍历策略与变换规则解耦。上层是四参数类型化光学脊柱,将光学表示为可检查、可比较、可前缀提取/后缀切分的带类型元素序列——每条光学是一条 profunctor 变换 P A B → P S T。
另外,为了给不同写法也应用这一套优化逻辑,本项目实现了一套小型编译器前端。
它读取可序列化 lambda 的 class-file 字节码并构建 LambdaExpr AST,在结构可证明时提升为专用 optic 节点,无法证明时则保留 opaque 语义。此篇讲了什么写法会被优化,什么不会 optics-usage-contract。
应用一次性提供自身的 MethodHandles.Lookup:可在 JPMS 的 module-info.java 中注册 OpticsLookupProvider,可在 classpath 下使用 META-INF/services,框架也可在收到业务 lookup 后调用 OpticsLookups.register(lookup);之后仍直接使用 Lens.of、Traversal.of、Prism.subtype 和 Optics.*,无需在每次调用时传 lookup。配置方式见 optics-usage-contract。
在真实应用型迁移基准中,本项目与 DFU 基本持平。把优化器场景单独拆出来看,两边仍会出现差异,整体属于平分秋色:有 DFU 更高的地方,也有本项目更高的地方。
本项目在优化器里保留了更严格的理论检查,因此部分单独拆出的优化器场景可能因为这些检查而不如 DFU,但真实开发中这类差异影响微乎其微。
基础 HKT 编码使用 K1、K2、App、App2、Kind1、Kind2 表示一元和二元类型构造子应用。当前包含的类型类和能力接口主要有:
FunctorApplicativeSelectiveMonadContravariantBifunctorNaturalSemigroupMonoidFoldableTraversableProfunctorCartesianStrongCocartesianChoiceClosedTraversingMappingAffinePMonoidalMonoidProfunctorFunctorProfunctorReCartesianReCocartesian
核心 profunctor carrier 和辅助结构包括:
FunctionArrowForgetForgetEForgetOptReForgetReForgetCReForgetEReForgetPReForgetEPProcomposeConstGrateWander
核心数据类型包括:
Maybe<A>Either<L, R>Try<A>Validated<E, A>CheckedFunction<A, B, X>等 checked-function 接口Tuple2<A, B>Tuple3<A, B, C>Tuple4<...>至Tuple16<...>IdF<A>Unit
时尚小垃圾。
com.flechazo.math 是一组用于验证和复用 HKT 表达能力的后端无关抽象。它允许你把态射、函子、坐标无关线性映射、张量形状、标量扩张和算子签名编码进 Java 类型,
并把表达式重化为可由 Natural transformation 解释的数学 IR。
对于 99.99% 的情况,这个包完全没有用。它不是数学计算库,不提供向量、矩阵、四元数或张量的具体值实现,也不提供数值算法、存储结构、SIMD、求解器或任何第三方数值后端适配。
本项目不选择、不包装也不发布数值后端;IR 只保存类型、变量、字面量和算子应用,不负责计算、优化或求值。
业务能力接口包括:
Composable<A>Combinable<A>Chainable<A>Effectful<A>Recoverable<E, A>Accumulating<E, A>
业务组合入口和路径类型包括:
PathwayMaybePath<A>EitherPath<E, A>TryPath<A>ValidationPath<E, A>ListPath<A>ReaderPath<R, A>WriterPath<W, A>WithStatePath<S, A>LazyPath<A>VTaskPath<A>IOPath<A>ResourcePath<A>IOResourcePath<A>CompletableFuturePath<A>StreamPath<A>VStreamPath<A>
业务上下文、控制和 effect 数据类型包括:
Reader<R, A>Writer<W, A>State<S, A>StateResult<S, A>ListK<A>ValidatedNelNonEmptyList<A>Lazy<A>VTask<A>IO<A>Resource<A>IOResource<A>ExitCaseFinalizers
业务 resilience API 包括:
ResilienceResilienceBuilder<A>RetryRetryPolicyRetryEventCircuitBreakerCircuitBreakerConfigCircuitBreakerMetricsBulkheadBulkheadConfigSaga<A>SagaBuilder<A>SagaStep<A>SagaError
业务 stream API 包括:
StreamK<A>FStream<F, A>VStream<A>VStreamParVStreamReactiveVStreamThrottleVStreamInstance
业务辅助 API 包括:
AttemptsMonoidsSemigroupsTraversesOptionalOps
会声明 checked exception 的 Java API 可以直接进入显式失败通道,不需要在
lambda 中手写 try/catch:
Try<String> content = Try.success(path)
.mapChecked(Files::readString)
.recover(NoSuchFileException.class, ignored -> "");
IO<String> deferred = IO.pure(path)
.mapChecked(Files::readString);Attempts.liftTry 用于 JDK Stream 等只接受普通 Function 的 API;
Attempts.uncheckedFunction 只用于明确要求 unchecked 传播的边界,并要求调用方
显式提供异常映射。批量转换使用 Attempts.traverse 进行 fail-fast 处理,或使用
Attempts.validateAll 累计错误。
资源获取和释放使用 Resource / IOResource。makeCase 的 finalizer 会收到
ExitCase.Succeeded、ExitCase.Failed 或 ExitCase.Canceled;多个 finalizer 通过
Finalizers.vtaskMonoid() 或 Finalizers.ioMonoid() 组合,全部执行并按顺序保留
suppressed failure。普通 optic getter、rebuilder 和 modifier 仍必须保持纯函数;
需要失败或 I/O 时使用 modifyF,具体契约见 docs/optics-usage-contract.md。
核心光学 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>
多态光学 API 包括:
PIso<S, T, A, B>PLens<S, T, A, B>PPrism<S, T, A, B>PAffine<S, T, A, B>PTraversal<S, T, A, B>PSetter<S, T, A, B>
带索引光学包括:
IndexedOptic<I, S, A>IndexedLens<I, S, A>IndexedTraversal<I, S, A>IndexedGetter<I, S, A>IndexedFold<I, S, A>
光学语义函数接口包括:
LensGetter<S, A>LensRebuilder<S, A, T>IsoGetter<S, A>IsoRebuilder<A, S>PrismMatcher<S, T, A>PrismBuilder<A, S>AffinePreview<S, T, A>AffineRebuilder<S, A, T>GetterReader<S, A>FoldGetter<S, A>WanderGetter<S, A>WanderRebuilder<S, A>SetterModifier<S, T, A, B>
常用实例和工具包括:
OpticsEachIxedAtTraversalsPrismsAffinesListPrismsListTraversalsStringTraversalsEitherTraversalsTryTraversalsValidatedTraversalsTupleTraversals
com.flechazo.optics.focus 提供轻量焦点 DSL,用于把生成出的焦点路径继续组合到 lens、traversal、affine 等光学结构。
参考:
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