SML中未解析flex记录的错误是什么?
我是SML的新手,曾向人们询问我遇到的错误。但是,我找不到问题所在 收到的错误消息是:SML中未解析flex记录的错误是什么?,sml,smlnj,Sml,Smlnj,我是SML的新手,曾向人们询问我遇到的错误。但是,我找不到问题所在 收到的错误消息是: stdIn:10.1-16.48 Error: unresolved flex record (need to know the names of ALL the fields in this context) type: {1:''Y, 2:''X; ''Z} 我有两个功能。第一个函数是reverse,它将列表反转并返回。例如,将[1,2,3,4]反转为[4,3,2,1]。这个函数绝对没有
stdIn:10.1-16.48 Error: unresolved flex record (need to know the names
of ALL the fields in this context)
type: {1:''Y, 2:''X; ''Z}
我有两个功能。第一个函数是reverse,它将列表反转并返回。例如,将[1,2,3,4]反转为[4,3,2,1]。这个函数绝对没有问题
fun reverse(L) =
if L = nil then nil
else reverse(tl(L)) @ [hd(L)];
下一个函数是getDirectNode,它接受3个参数:起始节点、包含边的元组列表和空列表。例如,我有一个节点1作为第一个参数。我有一个包含所有边的元组列表。[(1,2)、(1,3)、(2,3)、(2,4)],用于第二个参数。最后,第三个参数将是一个空列表
在getDirectNodes函数中,它将找到第一个数字为1的元组。在这种情况下,它将得到(1,2)和(1,3)。然后,它将把2和3放入空列表并返回。因此,函数将返回[2,3]
以下是我的功能:
fun getDirectNodes(startNode,Tuples,list) =
if Tuples = []
then list
else if #1(hd(Tuples)) = startNode
then getDirectNodes(startNode,tl(Tuples),reverse(#2(hd(Tuples)) :: list))
else
getDirectNodes(startNode, tl(Tuples),list)
什么可能导致此错误?您得到的错误是由SML编译器无法推断您拥有的元组类型引起的
#1
和#2
不是函数,而是可以处理任意类型元组的宏,只要它们有两个元素。所以克服这个问题的一个快速方法是添加类型注释
fun getDirectNodes(startNode, Tuples : (int * int) list, list) = ...
但是,由于您发布了大量解决方案,我想给出一些一般性的反馈:
颠倒
您的反向执行
有几处错误:
时,如果L=[]…
,您将强制L
成为一个。这似乎有些奇怪,因为您只是测试L
是否为空,但在L=[]
可以成为有效表达式之前,它的元素也必须是相等的。您可以通过模式匹配或使用函数List.null
(使用模式匹配)来解决此问题,以避免等式类型限制hd
和tl
代替模式匹配;这些函数是,这意味着如果使用不当,它们可能在运行时崩溃。您可以通过在空列表和非空列表上使用模式匹配来避免它们@
,这是非常低效的:您的算法是O(n²),因为@
的左侧需要线性时间来解析每个递归调用,即几何复杂度:
reverse [1,2,3,4]
~> reverse [2,3,4] @ [1]
~> reverse [3,4] @ [2] @ [1]
~> reverse [4] @ [3] @ [2] @ [1]
~> reverse [] @ [4] @ [3] @ [2] @ [1]
此时,reverse
使用了O(n)堆栈空间
~> [] @ [4] @ [3] @ [2] @ [1]
~> [4] @ [3] @ [2] @ [1] (* 1 recursive call in @ *)
~> [4,3] @ [2] @ [1] (* 2 recursive calls in @ *)
~> [4,3,2] @ [1] (* 3 recursive calls in @ *)
~> [4,3,2,1] (* 4 recursive calls in @ *)
此时,reverse
使用了O(n+(n-1)+…+1)=O(n²)递归调用rev
它是这样实现的:
fun rev xs =
let fun rev_helper [] xs_bw = xs_bw
| rev_helper (x::xs) xs_bw = rev_helper xs (x::xs_bw)
in rev_helper xs [] end
把它称为:
rev [1,2,3,4]
~> rev_helper [1,2,3,4] []
~> rev_helper [2,3,4] [1] (* 1 recursive call *)
~> rev_helper [3,4] [2,1] (* 1 recursive call *)
~> rev_helper [4] [3,2,1] (* 1 recursive call *)
~> rev_helper [] [4,3,2,1] (* 1 recursive call *)
~> [4,3,2,1]
它使用堆内存而不是堆栈内存,以及O(n)递归调用列表
作为累积结果是很好的!我可能会称之为更具描述性的东西,就像我会称之为Tuples
类似于edges
的东西来描述它的内容而不是类型一样list
这样的累积结果很整洁,但这意味着您的函数需要一个空列表作为输入。如果调用方向其提供一个非空列表怎么办?公开这个额外的参数会留下错误的空间,所以将其隐藏在内部函数中,就像我使用rev\u helper
时所做的那样hd
和tl
reverse
似乎很有意义:您已经体验到list
以反向结束。但是不要在每次递归调用时调用list
上的reverse
,而是在最末尾执行一次(当Tuples
为空时)fun getDirectNodes (startNode, []) = []
| getDirectNodes (startNode, (x, endNode) :: edges) =
if x = startNode
then endNode :: getDirectNodes (startNode, edges)
else getDirectNodes (startNode, edges)
以及一个变体,它使用一个内部尾部递归函数,并在末尾使用一个rev
:
fun getDirectNodes (startNode, edges) =
let fun helper ([], endNodes) = endNodes
| helper ((x, endNode) :: edges, endNodes) =
if x = startNode
then helper (edges, endNode :: endNodes)
else helper (edges, endNodes)
in rev (helper (edges, [])) end
下面是我将如何使用高阶函数实现它:
fun getDirectNodes (startNode, edges) =
List.map #2 (List.filter (fn (x, _) => x = startNode) edges)
我没有收到警告的原因。我在这里使用#2
,尽管没有任何类型注释,但这是因为我在代码fn(x,))=>…
中对边的元素进行模式匹配。这将边
约束为2元组列表
运行此:
- getDirectNodes (1, [(1,2),(1,3),(2,3),(2,4)]);
> val it = [2, 3] : int list