Grisette库中UnionM [UnionM SymInteger]操作函数实现咨询
Grisette中UnionM嵌套列表的元素删除优化实现与建模思路
问题背景
在使用Grisette处理符号整数列表时,由于mrgIf等条件操作返回UnionM SymInteger,需采用[UnionM SymInteger]类型存储数据。适配该类型实现pickLargest函数后,需要实现从列表中删除指定UnionM SymInteger元素的功能,但现有symDrop仅支持SymInteger参数,无法处理UnionM SymInteger及嵌套场景。自行实现的symListDrop需要手动解包UnionM,希望得到优化实现或更合理的建模思路。
优化后的symListDrop实现
直接针对[UnionM SymInteger]类型实现,避免不必要的UnionM包装,利用Grisette的原生组合子简化代码:
import Grisette symListDrop :: [UnionM SymInteger] -> UnionM SymInteger -> UnionM [UnionM SymInteger] symListDrop [] _ = mrgReturn [] symListDrop (x:xs) el = mrgIf (x .== el) (symListDrop xs el) (x `mrgCons` symListDrop xs el)
实现说明
- 直接接收
[UnionM SymInteger]作为输入,无需将列表套进UnionM,减少冗余的解包操作 - 用
mrgCons替代手动do块拼接列表,贴合Grisette的惯用写法,代码更简洁 - 递归逻辑清晰:若当前元素等于目标元素,返回剩余列表的处理结果;否则将当前元素拼接到剩余列表处理结果前
更合理的问题建模思路
如果需要频繁对[UnionM SymInteger]进行操作,可以从以下两种方向优化建模:
1. 改用SymList类型
Grisette提供的SymList原生支持符号化列表操作,无需手动处理UnionM嵌套:
import Grisette.Data.SymList -- 适配SymList的pickLargest pickLargestSym :: SymList SymInteger -> SymList SymInteger -> SymList SymInteger pickLargestSym = zipWithSym (\x y -> mrgIf (x .> y) x y) -- 基于SymList的元素删除 symListDropSym :: SymList SymInteger -> SymInteger -> SymList SymInteger symListDropSym = filterSym (/=)
若需处理UnionM SymInteger的列表,可结合SymList与UnionM实现:
symListDropUnion :: SymList (UnionM SymInteger) -> UnionM SymInteger -> UnionM (SymList (UnionM SymInteger)) symListDropUnion ls el = traverseSym (\x -> mrgIf (x .== el) mrgNothing (mrgJust x)) ls >>= mrgReturn . catMaybesSym
2. 封装通用过滤辅助函数
如果不想切换到SymList,可以封装通用的符号列表过滤函数,基于它实现删除逻辑:
symFilter :: (UnionM SymInteger -> UnionM SymInteger -> UnionM Bool) -> [UnionM SymInteger] -> UnionM SymInteger -> UnionM [UnionM SymInteger] symFilter _ [] _ = mrgReturn [] symFilter p (x:xs) el = do keep <- p x el rest <- symFilter p xs el mrgIf keep (mrgReturn (x:rest)) rest -- 基于通用过滤实现删除 symListDrop' = symFilter (\x el -> mrgNot (x .== el))
原代码问题分析
原实现将列表包装为UnionM [UnionM SymInteger],导致每次递归都需要手动用mrgReturn包装剩余列表,增加了代码复杂度。优化后的实现直接操作[UnionM SymInteger],借助Grisette的mrgIf和mrgCons等组合子,避免了不必要的monadic解包,代码更简洁高效。
内容的提问来源于stack exchange,提问作者Stefanos Baziotis
相关产品推荐
相关产品推荐

