我在Haskell总共n00b,我正在尝试使用DPLL编写一个简单的SAT求解器。
我有一个函数展开,它将(A1 and A2 ...) Or (B1 and B2 ...)
的模式转换为合欢的普通形式:(A1 or B1) and (A1 or B2) and ... (A2 or B2) and ...
。
我已将表达式数据类型表示如下
type Term = Int
data Expr = Or Expr Expr | And Expr Expr | Literal Term
(我不关心否定,因为我可以用-x表示Not(x)
但是现在,编写expand,看起来很难看到构造函数标签。
expnd (Literal l) (Literal r) = Or (Literal l) (Literal r)
expnd (Literal t) (And l r) = And (expnd (Literal t) l) (expnd (Literal t) r)
expnd (And l r) (Literal t) = And (expnd l (Literal t)) (expnd r (Literal t))
expnd (And l1 r1) (And l2 r2) =
And (And (expnd l1 l2) (expnd l1 r2)) (And (expnd r1 l2) (expnd r1 r2))
我可以将此代码更清洁吗?
答案 0 :(得分:2)
您可以在as
个案例中使用Literal
模式来删除一些冗余。例如,第一种情况可以写成
expnd l@(Literal _) r@(Literal _) = Or l r
答案 1 :(得分:1)
不,您编写的所有代码都是完全必要的。您在所有可能的参数上都有模式匹配,您需要重建结果。您可以通过充分利用关键字where
和let ... in
来使其更加清晰,但这会使其更长。
实际上,您有四行代码可以保证适用于此问题。这比大多数语言能够声称要好得多......
如果您想使用不同的方式来解决此问题,那么您可以使其更简单。
type Or a = [a]
type And a = [a]
为了清晰起见,我们会这样做,然后我们可以解决这个问题,
expand :: Or (And a) -> And (Or a)
expand [] = []
expand (x:xs) = zipWith (:) x (expand xs)
这应该有用,虽然我还没有测试过。