存在主义的搜索和查询没有大惊小怪

时间:2011-10-18 21:03:45

标签: algorithm search haskell logic

在没有实现嵌入式逻辑编程语言的情况下,是否有可扩展,有效的方法在Haskell中编写存在语句?通常,当我实现算法时,我想表达存在量化的一阶语句,如

∃x.∃y.x,y ∈ xs ∧ x ≠ y ∧ p x y

其中在列表上重载。如果我赶时间,我可能会写出看起来像

的明显代码
find p []     = False
find p (x:xs) = any (\y -> x /= y && (p x y || p y x)) xs || find p xs

find p xs = or [ x /= y && (p x y || p y x) | x <- xs, y <- xs]

但是这种方法并不能很好地概括为返回多个arities的值或谓词或函数的查询。例如,即使是像

这样的简单陈述
∃x.∃y.x,y,z ∈ xs ∧ x ≠ y ≠ z ∧ f x y z = g x y z

需要编写另一个搜索程序。这意味着大量的样板代码。当然,实现缩小或解析引擎的CurryProlog等语言允许程序员编写如下语句:

find(p,xs,z) = x ∈ xs & y ∈ xs & x =/= y & f x y =:= g x y =:= z

大量滥用表示法,它执行搜索并返回值。在实现形式上指定的算法时经常会出现此问题,并且通常通过fmapfoldrmapAccum等函数的组合来解决,但主要是显式递归。在Haskell中编写这样的代码是否有更通用,更高效,或者只是一般和富有表现力的方式?

2 个答案:

答案 0 :(得分:6)

有一个允许你转换的标准转换

∃x ∈ xs : P

exists (\x -> P) xs

如果您需要制作证人,可以使用find代替exists

在Haskell中进行这种抽象而不是逻辑语言真正令人讨厌的是,你真的必须必须将“Universe”集xs作为参数传递。我相信这就是你在标题中提到的“大惊小怪”。

当然,如果您愿意,您可以将通用集(通过其搜索)填充到monad中。然后,您可以定义自己的existsfind版本以使用monadic状态。为了提高效率,你可以尝试Control.Monad.Logic,但这可能涉及对奥列格的论文的打击。

无论如何,经典编码是用lambdas替换所有绑定结构,包括存在和通用量词,并继续进行适当的函数调用。我的经验是,这种编码甚至适用于具有大量结构的复杂嵌套查询,但它总是让人觉得笨重。

答案 1 :(得分:2)

也许我不明白,但列表理解有什么问题?你的第二个例子变成了:

[(x,y,z) | x <- xs, y <- xs, z <- xs
, x /= y && y /= z && x /= z 
, (p1 x y z) == (p2 x y z)]

这允许你返回值;要检查公式是否满足,只需使用null(由于懒惰,它的评估不会超过需要)。