如何像在 Prolog 中那样在 Mercury 中生成新变量列表?
How to generate lists of fresh variables in Mercury like I can in Prolog?
在 SWI Prolog 中,list(Xs) :- length(Xs, _).
是“纯”的,因为我可以向它传递一个具有任何类型实例化的变量,并且它将非确定性地将它与特定长度的所有最通用的统一器统一起来。
是否可以在Mercury中写一个纯list/1
? The manual seemed to hint this could be done,但我在实际执行时遇到了问题。
我目前拥有的是:
:- module mylist.
:- interface.
:- import_module list.
:- inst frees for list/1
---> []
; [free | frees].
:- mode free_to_frees == free >> frees.
:- pred mylist(list(_)).
:- mode mylist(in) is det.
:- mode mylist(free_to_frees) is multi.
:- implementation.
:- pragma promise_pure(mylist/1).
mylist(_::in).
mylist([]::free_to_frees).
mylist([_|Xs]::free_to_frees) :- mylist(Xs).
但是,当我尝试这样做时:
:- module main.
:- interface.
:- implementation.
:- import_module list, mylist.
:- pred getlist(list(int)).
:- mode getlist(free >> ground) is multi.
getlist(Xs) :- Xs = [1, 2, 3].
getlist(Xs) :- mylist(Xs), Xs = [5].
我收到以下错误:
main.m:011: In clause for `getlist(out)':
main.m:011: mode error in conjunction. The next 2 error messages indicate
main.m:011: possible causes of this error.
main.m:011:
main.m:011: In clause for `getlist(out)':
main.m:011: mode error in unification of `Xs' and `list.[V_10 | V_16]'.
main.m:011: Variable `Xs' has instantiatedness
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel,
main.m:011: which expands to
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel
main.m:011: )
main.m:011: )
main.m:011: )
main.m:011: ),
main.m:011: term `list.[V_10 | V_16]' has instantiatedness
main.m:011: `named inst list.'[|]'(unique(5), free)'.
main.m:011:
main.m:011: In clause for `getlist(out)':
main.m:011: in argument 1 of clause head:
main.m:011: mode error in unification of `HeadVar__1' and `Xs'.
main.m:011: Variable `HeadVar__1' has instantiatedness `free',
main.m:011: variable `Xs' has instantiatedness
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel,
main.m:011: which expands to
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel
main.m:011: )
main.m:011: )
main.m:011: )
main.m:011: ).
我猜我对 free
的使用可能不正确,否则我需要添加一个额外的模式或概括我的 listskel
inst 以涵盖 mylist(Xs), Xs = [5]
的情况。
基本上mylist/1
应该怎么写,才能在尽可能多的模式下使用?
谢谢!
由于 Mercury 实施中的限制,即
记录在 Mercury 发行版的 LIMITATIONS 文件中,
你所要求的无法完成。
虽然 Mercury 语言的设计允许模式描述
部分实例化的术语,例如自由变量列表,例如
mylist(Xs)
的预期输出,除非你能
对它们做一些事情,比如用 [5]
统一它们。由于 Mercury
编译器需要知道所有变量的实例化状态
程序点,它可以允许这个 only 如果它可以跟踪所有
自由变量与其他自由变量之间的统一
(无论它们是否以这种方式出现)。这是因为如果你有
统一 A = B
、B = C
和 C = D
,然后将 D
统一为 5
,
编译器需要知道这不仅基于 D
,还基于 A
、B
和 C
。这是因为这些统一使得 A
、B
和 C
别名
D
(即它们是指代 D
的其他方式)。
当 Mercury 在 90 年代中期首次实施时,我们有一个学生
致力于别名跟踪。不幸的是,他发现的是
别名跟踪 可能 ,但不 可行 ,因为它会切换
别名跟踪通常至少 加倍 所需的时间
编译一个模块。我们认为这是一个太高的代价
对于几乎从未使用过的功能。即使在今天,
由于摩尔定律,别名跟踪的绝对成本会很大
更小,相对权衡并没有真正改变,我们现在有
几十年与 Mercury 合作的经验
发现很少有支持部分填充的情况
实例化的数据结构会很有用
我一个都不记得了。
Mercury 中的编程与 Prolog 中的编程有很大不同。
这是设计使然。在 Mercury 中,而不是构建部分
实例化术语然后填充它,您只需构造
直接最后一项。对于任何对程序感兴趣的程序员
可靠性,这将是首选的行动方案,即使
在序言中工作。在真正的 Prolog 程序中,与解谜器相反
或学生练习,保留部分未实例化的术语要多得多
很可能是一个错误。
在 SWI Prolog 中,list(Xs) :- length(Xs, _).
是“纯”的,因为我可以向它传递一个具有任何类型实例化的变量,并且它将非确定性地将它与特定长度的所有最通用的统一器统一起来。
是否可以在Mercury中写一个纯list/1
? The manual seemed to hint this could be done,但我在实际执行时遇到了问题。
我目前拥有的是:
:- module mylist.
:- interface.
:- import_module list.
:- inst frees for list/1
---> []
; [free | frees].
:- mode free_to_frees == free >> frees.
:- pred mylist(list(_)).
:- mode mylist(in) is det.
:- mode mylist(free_to_frees) is multi.
:- implementation.
:- pragma promise_pure(mylist/1).
mylist(_::in).
mylist([]::free_to_frees).
mylist([_|Xs]::free_to_frees) :- mylist(Xs).
但是,当我尝试这样做时:
:- module main.
:- interface.
:- implementation.
:- import_module list, mylist.
:- pred getlist(list(int)).
:- mode getlist(free >> ground) is multi.
getlist(Xs) :- Xs = [1, 2, 3].
getlist(Xs) :- mylist(Xs), Xs = [5].
我收到以下错误:
main.m:011: In clause for `getlist(out)':
main.m:011: mode error in conjunction. The next 2 error messages indicate
main.m:011: possible causes of this error.
main.m:011:
main.m:011: In clause for `getlist(out)':
main.m:011: mode error in unification of `Xs' and `list.[V_10 | V_16]'.
main.m:011: Variable `Xs' has instantiatedness
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel,
main.m:011: which expands to
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel
main.m:011: )
main.m:011: )
main.m:011: )
main.m:011: ),
main.m:011: term `list.[V_10 | V_16]' has instantiatedness
main.m:011: `named inst list.'[|]'(unique(5), free)'.
main.m:011:
main.m:011: In clause for `getlist(out)':
main.m:011: in argument 1 of clause head:
main.m:011: mode error in unification of `HeadVar__1' and `Xs'.
main.m:011: Variable `HeadVar__1' has instantiatedness `free',
main.m:011: variable `Xs' has instantiatedness
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel,
main.m:011: which expands to
main.m:011: bound(
main.m:011: []
main.m:011: ;
main.m:011: '[|]'(
main.m:011: free,
main.m:011: named inst mylist.listskel
main.m:011: )
main.m:011: )
main.m:011: )
main.m:011: ).
我猜我对 free
的使用可能不正确,否则我需要添加一个额外的模式或概括我的 listskel
inst 以涵盖 mylist(Xs), Xs = [5]
的情况。
基本上mylist/1
应该怎么写,才能在尽可能多的模式下使用?
谢谢!
由于 Mercury 实施中的限制,即 记录在 Mercury 发行版的 LIMITATIONS 文件中, 你所要求的无法完成。
虽然 Mercury 语言的设计允许模式描述
部分实例化的术语,例如自由变量列表,例如
mylist(Xs)
的预期输出,除非你能
对它们做一些事情,比如用 [5]
统一它们。由于 Mercury
编译器需要知道所有变量的实例化状态
程序点,它可以允许这个 only 如果它可以跟踪所有
自由变量与其他自由变量之间的统一
(无论它们是否以这种方式出现)。这是因为如果你有
统一 A = B
、B = C
和 C = D
,然后将 D
统一为 5
,
编译器需要知道这不仅基于 D
,还基于 A
、B
和 C
。这是因为这些统一使得 A
、B
和 C
别名
D
(即它们是指代 D
的其他方式)。
当 Mercury 在 90 年代中期首次实施时,我们有一个学生 致力于别名跟踪。不幸的是,他发现的是 别名跟踪 可能 ,但不 可行 ,因为它会切换 别名跟踪通常至少 加倍 所需的时间 编译一个模块。我们认为这是一个太高的代价 对于几乎从未使用过的功能。即使在今天, 由于摩尔定律,别名跟踪的绝对成本会很大 更小,相对权衡并没有真正改变,我们现在有 几十年与 Mercury 合作的经验 发现很少有支持部分填充的情况 实例化的数据结构会很有用 我一个都不记得了。
Mercury 中的编程与 Prolog 中的编程有很大不同。 这是设计使然。在 Mercury 中,而不是构建部分 实例化术语然后填充它,您只需构造 直接最后一项。对于任何对程序感兴趣的程序员 可靠性,这将是首选的行动方案,即使 在序言中工作。在真正的 Prolog 程序中,与解谜器相反 或学生练习,保留部分未实例化的术语要多得多 很可能是一个错误。