如何在JavaScript中对PureScript和积类型做模式匹配识别LongMessage值
PureScript ADT值在JavaScript侧的构造器识别方法
你遇到的是PureScript和JavaScript互操作时的ADT类型识别问题,有两种可行方案:
快速临时方案:基于构造器名称判断
PureScript编译sum-of-products类型时,会为每个构造器生成专属的JS构造函数,构造函数名格式为你定义的构造器名+数字索引,你在控制台看到的LongMessage3就遵循这个规则。
可以直接通过实例的构造器名前缀判断类型,不需要关心后缀的索引值(索引会随构造器定义顺序、编译器版本变化,不要硬编码完整名称做相等匹配):
// 执行initialize拿到IO实例 const ioVal = Main.initialize(); // 判断是否为LongMessage构造器生成的值 if (ioVal.constructor.name.startsWith('LongMessage')) { // 构造器参数按定义顺序存在value0、value1...属性上 const stringArray = ioVal.value0; // 对应Array String参数 const nextIoEffect = ioVal.value1; // 对应Effect IO参数 // 要继续执行后续IO逻辑,直接调用nextIoEffect()即可拿到下一个IO值 } // 其他构造器判断逻辑同理,比如判断End就判断startsWith('End')
生产环境稳妥方案:从PureScript侧导出判断/解构函数
直接依赖JS侧的构造器命名属于耦合编译器内部实现的写法,编译器版本升级、构造器顺序调整都可能导致逻辑失效。更推荐的做法是在PureScript代码中提前编写类型判断、值解构的辅助函数导出给JS侧调用:
首先在PureScript源码中添加:
-- 判断值是否由LongMessage构造器生成 isLongMessage :: IO -> Boolean isLongMessage (LongMessage _ _) = true isLongMessage _ = false -- 解构LongMessage的参数,返回Maybe避免非LongMessage值调用报错 unLongMessage :: IO -> Maybe { strArr :: Array String, nextEffect :: Effect IO } unLongMessage (LongMessage strArr nextEffect) = Just { strArr, nextEffect } unLongMessage _ = Nothing -- 其他构造器的判断、解构函数可按相同模式编写
编译后在JS侧直接调用导出的函数即可,完全不需要关心PureScript的内部编译规则:
const ioVal = Main.initialize(); if (Main.isLongMessage(ioVal)) { const payload = Main.unLongMessage(ioVal).value0; const stringArray = payload.strArr; const nextIoEffect = payload.nextEffect; // 业务逻辑 }
内容的提问来源于stack exchange,提问作者Cactus
相关产品推荐
相关产品推荐

