寻求Haskell concat函数的Prolog等价实现,处理特定嵌套列表拼接
实现Haskell concat风格的Prolog嵌套列表拼接
你要的其实不是完全展平整个列表,而是针对嵌套列表的每一层子列表做拼接——把每个内部的小列表合并成一个,最终得到外层保留原层级、内层为拼接后列表的结果。针对你给出的例子[[[a],[b]],[[c],[d]]] → [[a,b],[c,d]],我来给你两种实用的实现方式:
方式一:自定义递归谓词
先写一个辅助谓词append_all/2,用来把一个列表中的所有子列表依次拼接成一个列表;再写主谓词concat_sublists/2,遍历外层列表的每个元素,对每个元素调用append_all并收集结果:
% 空列表的基准情况 concat_sublists([], []). % 处理非空列表:对第一个子列表做拼接,递归处理剩余部分 concat_sublists([Sublist | Rest], [FlatSublist | RestFlats]) :- append_all(Sublist, FlatSublist), concat_sublists(Rest, RestFlats). % 把列表中的所有子列表拼接成一个列表 append_all([], []). append_all([Current | Remaining], Result) :- append_all(Remaining, TempResult), append(Current, TempResult, Result).
测试这个谓词:
?- concat_sublists([[[a],[b]],[[c],[d]]], Result). Result = [[a, b], [c, d]] ; false.
方式二:用内置谓词简化
Prolog的foldl和maplist可以让代码更简洁。foldl(append, Sublist, [], Flat)会把Sublist里的所有子列表从左到右依次拼接到空列表上,正好实现append_all的功能;再用maplist把这个操作应用到外层列表的每个元素上:
concat_sublists(List, Result) :- maplist(append_sublists, List, Result). append_sublists(Sublist, Flat) :- foldl(append, Sublist, [], Flat).
同样测试:
?- concat_sublists([[[a],[b]],[[c],[d]]], Result). Result = [[a, b], [c, d]].
这个版本更紧凑,利用了Prolog的高阶谓词,可读性也不错。
内容的提问来源于stack exchange,提问作者nocturne
相关产品推荐
相关产品推荐

