Clojure 康达,康迪,康德,康杜
我在看书 我对conde的工作原理有一些直觉 然而,我找不到一个正式的定义来定义conde/Clojure 康达,康迪,康德,康杜,clojure,scheme,clojure-core.logic,minikanren,reasoned-schemer,Clojure,Scheme,Clojure Core.logic,Minikanren,Reasoned Schemer,我在看书 我对conde的工作原理有一些直觉 然而,我找不到一个正式的定义来定义conde/conda/condu/condi做什么 我知道,但这似乎有例子,而不是定义 用Prolog的术语来说,conde、conda、condi、condu是否有正式的定义 康达是“软切割”a.k.a.*->,其中a*->B;C就像(A,B;不是(A),C),只是更好 ; 鉴于 condU是“承诺的选择”,是一种一次和软剪切的组合,因此(一次(a)*->B;false)表示(a,!,B)(剪切在里面):
conda
/condu
/condi
做什么
我知道,但这似乎有例子,而不是定义
用Prolog的术语来说,conde
、conda
、condi
、condu
是否有正式的定义
是“软切割”a.k.a.康达
,其中*->
就像a*->B;C
,只是更好 ; 鉴于(A,B;不是(A),C)
是“承诺的选择”,是一种condU
和软剪切的组合,因此一次
表示(一次(a)*->B;false)
(剪切在里面):(a,!,B)
condA:A*->B;C%软切,
%(A、B;非(A)、C)
条件:一次(A)*->B;C%承诺选择,
%(A,!,B;不是(A),C)
(分别用;
表示“或”和,
表示“和”,即目标的分离和连接)
在condA
中,如果目标A
成功,所有解决方案都会传递到第一个子句B
,并且不会尝试任何替代子句C
在condU
中,一次/1
只允许其参数目标成功一次(仅保留一个解决方案,如果有的话)
condE
是一个简单的连词析取,而condI
是一个在其成分的溶液之间交替的析取,交错其中的流
下面是一个忠实地将本书的代码(包括逻辑变量和统一)翻译成18行Haskell的尝试,Haskell主要是一个带有语法的惰性Lisp,其中
- 简单并置是当前函数应用程序,
fabc=~=((fa)b)c)=~=f(a,b,c)
是lambda函数,(\a->b)
(lambda(a)b)
是foo x=y
foo=(\x->y)
是a@b=y
的快捷方式,中缀运算符的定义(@)a b=y
@
- 括号
(
仅用于分组)
是空列表,并且[]
表示cons——在定义中位于:
右侧的构造函数(惰性,因为整个语言都是惰性的,即根据需要调用);作为一种分解模式,在左侧(或在模式匹配=
表达式中)case
- 顺序流组合(“本书的mplus
(1)[]+:ys=ys
(2) (x:xs++:ys=x:(xs++:ys)
- 交替流组合(“
”):mplusI
(3)[]+/ys=ys (4) (x:xs)+/ys=x:(ys++/xs)
- 顺序馈送(“
”):bind
(5)[]>:g=[] (6) (x:xs)>>:g=gx++:(xs>>:g)
- 交替馈送(“
”):bindI
(7)[]>/g=[] (8) (x:xs)>>/g=gx++/(xs>>/g)
- “
”目标组合(或
”):condE
(9)(f | |:g)x=f x++:g x
- “交替
”目标组合(或
):condI
(10)(f | |/g)x=f x++/g x
- “
”目标组合(和
”):全部
(11)(f&&:g)x=fx>:g
- “交替的
和
”目标组合(“本书的
”):allI
(12)(f&/g)x=f x>>/g
- 特殊目标
(13)true x=[x]--重新打包相同解决方案的sigleton列表 (14) false x=[]--一个空列表,表示该解决方案被拒绝
(全部)=真
(全部g1)=g1
(所有g2 g3…=(\x->g1 x>>:(所有g2 g3…)
=g1&:(g2&:(g3&:…)
(allI g1 g2 g3…=(\x->g1 x>>/(allI g2 g3…)
=g1&/(g2&/(g3&/)
condX
的重写规则为:
(condX)=错误
(condX(其他g1-g2…)=(所有g1-g2…)=g1&:(g2&&:(…)
(condX(g1-g2…)=(所有g1-g2…)=g1&:(g2&:(…)
(condX(g1-g2…)(h1-h2…)=(ifX-g1(所有g2…)
(ifX h1(所有h2…))
为了最终实现condE和condI的翻译,无需实现本书的ifE和ifI,因为它们进一步简化为简单的运算符组合,所有操作符都被认为是右关联的:
(冷凝器(g1 g2…(h1 h2…)=
(g1&&:g2&&:…)| |:(h1&&:h2&:…)|:。。。
(条件(g1 g2…(h1 h2…)=
(g1&&:g2&:…)| |/(h1&&:h2&:…)|//。。。
所以在Haskell中不需要任何特殊的“语法”,简单的二进制中缀运算符就足够了。
user> (run* [w q]
(conde [u#]
[(or* [(== w 1) (== w 2)])
(== q :first)]
[(== q :second)]))
([_0 :second] [1 :first] [2 :first])
user> (run* [w q]
(conda [u#]
[(or* [(== w 1) (== w 2)])
(== q :first)]
[(== q :second)]))
([1 :first] [2 :first])
user> (run* [w q]
(condu [u#]
[(or* [(== w 1) (== w 2)])
(== q :first)]
[(== q :second)]))
([1 :first])
once(A) *-> B;C