Algorithm 无需大惊小怪的存在搜索和查询

Algorithm 无需大惊小怪的存在搜索和查询,algorithm,search,haskell,logic,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 或 需要编写另一个搜

有没有一种可扩展的、有效的方法可以不用实现嵌入式逻辑编程语言就用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

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

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

大量滥用符号,它执行搜索并返回值。这个问题通常在实现正式指定的算法时出现,通常通过组合函数来解决,如
fmap
foldr
、和
mapacum
,但主要是显式递归。在Haskell中,有没有一种更通用、更高效,或者更通用、更富有表现力的方法来编写这样的代码?

也许我不懂一些东西,但是列表理解有什么问题吗?第二个例子是:

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

[(x,y,z)| x有一个标准转换,允许您转换

∃x ∈ xs : P

如果需要出示证人,可以使用
find
而不是
exists

在Haskell中进行这种抽象而不是在逻辑语言中进行这种抽象的真正讨厌之处在于,您确实必须将“宇宙”集
xs
作为参数传递。我相信这就是您在标题中提到的“大惊小怪”的原因

当然,如果您愿意,您可以将通用集(您正在通过它进行搜索)填充到一个单子中。然后您可以定义自己的
exists
find
版本,以处理单子状态。为了使其有效,您可以尝试,但这可能需要打破您对Oleg论文的理解


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

我怀疑这就是您想要的这个实现的问题是,如果
p1xyz==p2xyz
x==xs!!1
xs
是无限的
find
将永远不会终止。这就是
LogicT
实现
msplit
和“公平析取”
交织的原因是的,我认为LogicT monad就是我想要的我在找。谢谢你的回复。我对你提到的代理很熟悉,也觉得很麻烦。
[(x,y,z) | x <- xs, y <- xs, z <- xs
, x /= y && y /= z && x /= z 
, (p1 x y z) == (p2 x y z)]
∃x ∈ xs : P
exists (\x -> P) xs