除了@firefrorefiddle 的回答,我还想注意三件事。首先,在使用皮亚诺数时,更习惯使用函子 s/1 来表示后继,使用 X 等单个字母表示变量,从而获得更小的项:
s(X) succ(Count)
s(s(X)) succ(succ(Count))
s(s(s(X))) succ(succ(succ(Count)))
s(s(s(s(X)))) succ(succ(succ(succ(Count))))
. .
. .
. .
其次,为了进一步提高可读性,最好为 DCG 选择一个不同的名称,比如 language//1 而不是 s//1。第三,您可以定义一个更通用的 DCG,让您指定一个元素及其在列表中的出现次数a
,b
而不是为 和 编写相同的 DCG 规则。c
将所有这些放在一起,您的 DCG 可能看起来像这样:
language(s(s(X))) -->
element_frequency(a,s(s(X))),
element_frequency(b,s(X)),
element_frequency(c,X).
element_frequency(_E,0) -->
[].
element_frequency(E,s(X)) -->
[E],
element_frequency(E,X).
在上面的代码中,language//1 对应于代码中的 s//1,element_frequency//2 是 a//1、b//1 和 c//1 的替换。如果您查询此 DCG,您会发现它仍然会产生与 @firefrorefiddle 帖子中的答案相同的答案,例如:
?- phrase(language(s(s(s(0)))),L).
L = [a,a,a,b,b,c]