Haskell中newtype嵌套结构下Literal过滤函数实现问题
Haskell合取范式Literal过滤函数实现方案
问题分析
你定义的And、Or都是newtype包装的容器,直接用map会触发类型不匹配错误——map作用于列表,而And x是包装了[Or x]的新类型,不能直接当作列表操作。另外你的代码存在拼写错误:Lit应为Literal,且未处理Negation构造器,也没把过滤后的结果重新包装回Or和And类型。
实现思路
- 拆包与打包:newtype本质是零开销包装,需要先把
And拆成内部的[Or x],处理完再重新包成And;同理Or也要拆成[Literal x],过滤后再包回Or。 - 覆盖所有Literal构造器:过滤逻辑要同时处理
Literal x和Negation x,根据实际需求决定是否保留。
代码实现
假设condition是判断x是否满足条件的函数(类型为x -> Bool),可以这样实现:
data Literal x = Literal x | Negation x deriving (Show, Eq) newtype Or x = Or [Literal x] deriving (Show, Eq) newtype And x = And [Or x] deriving (Show, Eq) -- 过滤单个Or结构中的Literal filterOr :: (x -> Bool) -> Or x -> Or x filterOr cond (Or literals) = Or $ filter keepLiteral literals where keepLiteral (Literal x) = cond x keepLiteral (Negation x) = cond x -- 可按需修改,比如只保留非否定Literal就设为False -- 过滤整个And结构中的Literal filterLit :: (x -> Bool) -> And x -> And x filterLit cond (And ors) = And $ map (filterOr cond) ors
关键细节说明
- newtype的拆包与打包:通过模式匹配
(And ors)取出内部的[Or x],处理完成后用And构造器重新包装,这是newtype操作的核心要求。 - 完整处理Literal分支:
keepLiteral函数匹配了Literal和Negation两个构造器,你可以根据业务需求调整逻辑,比如仅保留非否定的Literal,就把Negation分支的返回值改为False。 - 严格保持类型一致性:每个处理函数的输入输出都严格对应自定义的新类型,避免类型不匹配错误。比如
filterOr输入Or x输出Or x,filterLit输入And x输出And x。
测试示例
定义判断是否等于1的条件函数,测试过滤效果:
testAnd :: And Int testAnd = And [Or [Literal 1, Negation 2], Or [Literal 3, Negation 1]] main = print $ filterLit (==1) testAnd -- 输出:And [Or [Literal 1], Or [Negation 1]]
内容的提问来源于stack exchange,提问作者K D
相关产品推荐
相关产品推荐

