Effect 的 Filter 除了 catchFilter 还能用在哪?
我写好一个 Filter 之后第一反应是顺手传给 Option.filter 或 Stream.filter,结果类型检查直接报错。更危险的是绕过类型检查:Filter 返回的 Result 总是 truthy,所有元素都会「通过」。
Filter 能复用在 filterMap 一族和 Stream.catchFilter 上;Option.filter 与 Stream.filter 收的是布尔谓词,要用就先 Filter.toPredicate 降级。
Filter 本质是 (input) => Result<Pass, Fail>,通过时可以变换值,所以它天然对应「过滤加映射」,而不是「只过滤」。Filter 的定义与 catchFilter 的用法见 Effect.catchFilter 怎么同时匹配并提取错误?。
哪些 API 可以直接收 Filter?
我验证过的复用点:
Array.filterMap(array, filter):对数组做过滤加变换。用主文章里的evenHalf(偶数折半,奇数不通过),[1,2,3,4]得到[1, 2]。Option.filterMap(option, filter):通过时是Some,否则None。Stream.filterMap(filter):流上的同一语义。Stream.catchFilter(filter, handler):流的错误恢复版本。
哪些 API 收的是谓词,不是 Filter?
Option.filter 和 Stream.filter。它们收布尔谓词。如果传 Filter,类型检查会报错;一旦绕过类型检查,Filter 返回的 Result 总是 truthy,会让所有元素「通过」。
要在这两处用 Filter,有两条路:先用 Filter.toPredicate 降级成谓词,或者改用 filterMap。Filter.toOption、Filter.toResult 可以把它降级成 Option 或 Result,我验证过 Filter.toOption(...) 通过时是 Some。
该降级还是该换成 filterMap?
如果你需要 Filter 提取出来的值,用 filterMap,因为降级成谓词会丢掉变换结果。如果你只需要「是否通过」,Filter.toPredicate 够用。我自己倾向前者,因为判断和提取只写一次,这正是 Filter 存在的理由。
以上基于 effect@4.0.5。Array.filterMap配evenHalf得到[1, 2]、Filter.toOption通过时为Some,以及Option.filter/Stream.filter收谓词而非 Filter(类型检查会报错),这几点本地验证过。Option.filterMap与Stream.filterMap/Stream.catchFilter的行为我没有逐个运行,请自己用编译器确认。「该降级还是该换成 filterMap」的取舍是我的推论。