2017-11-11 85 views
1

我试着理解序言。我想给输入:转换(S(S(S(X))),Y)和输出应该是Y = 3返回整数与Prolog

convert(s(0), 1). 
convert(s(s(0)), 2). 
convert(s(X),Y) :- convert(X,Y is (Y+1)). 

这些都是我的规则的权利,但只有输入: convert(s(0),1)。并且 convert(s(s(0)),2)。工作。转换(s(s(0)),2)。如果我的递归会正常工作,我不需要规则:convert(s(s(0)),2)。 有人可以帮我解决这个问题吗?

电贺

回答

1

有两个问题在这里:

  • Y is Y+1,不使任何意义的序言;和
  • 请注意,你这里实际上已经写了一个函子

Prolog的认为这是一个电话:

convert(X,is(Y,Y+1)) 

其中is(Y,Y+1)叫,但作为一个仿函数传递。在Prolog中,没有明确的输入和输出。你调用谓词并通过统一,你获得结果。

我们可以但是解决使用递归的问题:0convert/2当然0的:

convert(0,0). 

s(X)的转换,是X加一的转换:

convert(s(X),R) :- 
    convert(X,Y), 
    R is Y+1. 

或将它们放在一起:

convert(0,0). 
convert(s(X),R) :- 
    convert(X,Y), 
    R is Y+1. 

现在我们可以调用谓词来列出所有的Peano数字和相应的数字,并将Peano数字转换为数字。我们还可以验证Peano号码是否为正常号码。

不幸的是,我们不能使用这个谓词从一个给定的数字中获得Peano数字:它将与Peano数字相一致,但是为了寻找另一个Peano数字,它将陷入无限循环。

我们可以使用clpfd库来帮助我们解决这个:

:- use_module(library(clpfd)). 

convert(0,0). 
convert(s(X),R) :- 
    R #> 0, Y #= R-1, 
    convert(X,Y).
+0

感谢,它的工作原理!但为什么重要的是给一个像R这样的大写字母: convert(s(X),R) 但为什么不是convert(s(X),r)工作? – Runner

+1

@Runner:因为变量以大写字母开头,所以常量是小写字母。这不是一个惯例(所以不这样做会使程序不正确)。如果不想听起来令人讨厌或者类似的话,或许你应该查看关于Prolog的一些基础知识。 –

+0

虽然正确,但您的clpfd版本效率极低,因为它需要很多临时变量。那么高效版本呢?啊,和s(X)的确如此。 – false