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

如何将Haskell中的单子式校验改写为Applicative形式?

实现方案

你说的没错,两个校验逻辑不存在先后依赖,完全可以用Applicative实现,这里给出两种符合需求的写法:

方式1:组合校验谓词后单次调用ensure

利用(->) a的Applicative实例,把两个独立的谓词组合为同时满足的复合谓词,再调用你的ensure函数校验:

import Control.Applicative (liftA2)

-- 等价于 ensure (\x -> x > 0 && x < 100) x
let validated = ensure (liftA2 (&&) (>0) (<100)) x

这里liftA2 (&&)把两个Int -> Bool类型的谓词,组合为一个新的Int -> Bool谓词,仅当输入同时满足两个原始谓词时返回True,全程用Applicative接口完成组合,没有手动写lambda拼接条件。

方式2:保留两次ensure调用的结构

如果要和你原写法的两次ensure调用结构对齐,直接在Maybe Applicative上下文内组合两次校验结果即可:

let validated = const <$> ensure (>0) x <*> ensure (<100) x

这段代码的逻辑和原Monad写法完全等价:

  • 只要任意一次ensure返回Nothing,整个表达式结果就是Nothing
  • 两次校验都通过时,会返回Just x,和原输出完全一致

补充说明

Applicative适用的核心前提就是多个计算逻辑之间没有依赖,你这里的两个范围校验刚好符合这个特征,不需要前一步的输出作为后一步的输入,所以完全可以用Applicative替换Monad写法,逻辑上没有任何差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 08:15:00