简化Haskell中的构造函数标记

时间:2014-01-18 03:26:48

标签: haskell constructor

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

我可以将此代码更清洁吗?

2 个答案:

答案 0 :(得分:2)

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

expnd l@(Literal _) r@(Literal _) = Or l r

答案 1 :(得分: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)

这应该有用,虽然我还没有测试过。