如何解决如何在 Prolog 中从 Haskell 编写 init 函数
init :: [a] -> [a]
init [_] = []
init (x:xs) = x : init xs
制定适当的 Prolog 规则 init(Xs,Ys)
,如果
(且仅当)Ys
是 Xs
的初始部分。
即查询
init([1,2,3,4,5],[1,4]).
将评估为 true
,或查询
init([1,Ys).
会给 Ys = [1,4]
。
解决方法
将您的 Haskell 代码直接转换为 Prolog 代码是:
init([_],[]) :- !.
init([X|Xs],[X|Ys]) :-
init(Xs,Ys).
直接翻译的结果:
?- init([1,2,3,4,5],[1,4]).
true.
?- init([1,Ys).
Ys = [1,4].
?- init([1,3]). % does not work properly!
false.
但是,正如定义的那样,谓词 init/2
不能正常工作(因为列表可以有几个不同的初始部分,或前缀)。因此,稍微好一点的翻译是:
init(_,[]). % assuming that first argument is any list!
init([X|Xs],Ys).
修改翻译的结果:
?- init([1,Ys).
Ys = [] ;
Ys = [1] ;
Ys = [1,2] ;
Ys = [1,3] ;
Ys = [1,4] ;
Ys = [1,5].
?- init([1,3]).
true.
,
首先将您的定义转换为 SSA 形式:
init [_] = []
init (x:xs) = rs where { rs = x:ys ; ys = init xs }
(在 Prolog 翻译中不需要也不需要类型签名)。
现在做句法欺骗:
init([_],[]).
init([X|XS],RS) :- RS = [X|YS],init( XS,YS) .
因为在 Haskell 中只有 first 匹配子句触发,即每个子句在它之后都有一个隐式切割,添加切割:
initc([_],[]) :- !.
initc([X|XS],RS) :- RS = [X|YS],initc( XS,YS) .
完成。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。