2014-01-18 16 views
1

我是Haskell中的总计n00b,我正在尝试使用DPLL编写简单的SAT求解器。在Haskell中简化构造函数标签

我有一个函数展开,从(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)与-x)

但现在,写作拓展,使用构造函数标签看起来非常难看。

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)) 

我可以让这个代码更清洁吗?

回答

2

您可以在Literal个案中使用as模式来删除一些冗余。例如,第一种情况可写为

expnd [email protected](Literal _) [email protected](Literal _) = Or l r 
+0

谢谢。这是我一直在寻找的。 – avak

1

不,你写的所有代码都是完全必要的。您对所有可能的参数都有模式匹配,并且需要重建结果。您可以充分利用关键字wherelet ... in使其变得更加清洁,但这会使其更长。

就这样,您有四行代码保证可以解决此问题。这是远远好于大多数语言能够声称的...


如果你想用处理这个问题的不同的风格,那么你可以把它简单。

type Or a = [a] 
type And a = [a] 

我们会做的,为了清楚,然后我们就可以解决这样的问题,

expand :: Or (And a) -> And (Or a) 
expand []  = [] 
expand (x:xs) = zipWith (:) x (expand xs) 

这应该工作,虽然我没有测试出来。