如何解决SML中else if语句中的"unresolved flex record"?

How to solve "unresolved flex record" in else if statement in SML?

我想找到当前给定节点直接或间接连接到的节点列表。 例如,我有一个节点列表:

[1,2]

和一个元组列表,每个元组代表一条直接边:

[(1,5),(2,4),(4,6)]

所以,我要找的节点是

[1,2,5,4,6]

因为,1接5,2接4,然后,4接6。 为此,我需要两个队列和一个列表。每次发现新节点时,我们都会将新节点添加到队列和列表中。然后,我们删除队列的第一个节点,并转到下一个节点。如果一个新节点连接到队列的当前节点。然后,我们将新节点添加到队列和列表中。

我们一直这样做,直到队列为空并且我们 return 列表。

所以现在,我有一个附加函数,可以将一个列表附加到另一个列表:

fun append(xs, ys) = 
   case ys of 
        [] => xs
    | (y::ys') => append(xs @ [y], ys')

然后,我有一个名为 getIndirectNodes 的函数,它打算 return 给定节点间接连接到的节点列表,但抛出 "unresolved flex record"。 List1 和 List2 应该有相同的项目。但是,List1 服务于队列,而 list2 服务器作为要 returned 的列表。

  fun getIndirectNode(listRoleTuples, list1, list2) =
      if list1 = []
          then list2
     else if hd(list1) = #1(hd(listRoleTuples))
        then (
            append(list1,#2(hd(listRoleTuples)) :: []);
            append(list2,#2(hd(listRoleTuples)) :: []);
            getIndirectNode(listRoleTuples,tl(list1),list2)
            )
        else
           getIndirectNode(listRoleTuples,tl(list1),list2)

如果我删除 else if 语句,它就可以正常工作。但是,这不是我打算做的。问题出在 else if 语句中。我能做些什么来修复它?

SML 需要确切知道元组的形状才能解构它。
您可以指定参数的类型 - listRoleTuples : (''a * ''a) list - 但使用模式匹配是更好的主意。

(该代码还有许多其他问题,但这就是您问题的答案。)

您的一位同学似乎在 中遇到了这个元组问题。

确保在再次问同样的问题之前浏览 Whosebug 问答。

关于获取间接节点,可以通过定点迭代解决

先获取所有直连节点,再获取直连节点的直连节点

然后递归地执行此操作,直到不再有新节点以这种方式出现。

fun getDirectNodes (startNode, edges) =
    List.map #2 (List.filter (fn (node, _) => node = startNode) edges)

fun toSet xs =
    ... sort and remove duplicates ...

fun getReachableNodes (startNodes, edges) =
    let
      fun f startNode = getDirectNodes (startNode, edges)
      val startNodes = toSet startNodes
      val endNodes = toSet (List.concat (List.map f startNodes))
    in
      if startNodes = endNodes
      then endNodes
      else getReachableNodes (startNodes @ endNodes, edges)
    end

这并不能完全找到间接端节点;它发现 startNodes 可以直接或间接访问的所有节点,并且它包括 startNodes 自身,即使它们本身不能直接或间接访问。

我试图通过使用 sets 作为数据类型来简化此练习;使用集合类型的实际、高效的实现会更整洁,例如使用平衡二叉搜索树。通过向集合中添加元素更容易查看是否有新节点,因为如果集合中已经包含元素,则在添加元素之前和之后它将等同于自身。

并且我尝试在有意义的时候使用高阶函数。例如,给定一个列表,其中我想对每个元素执行相同的操作,List.map 会生成一个结果列表。但是由于我想做的事情,getDirectNodes (startNode, edges) 生成一个列表,然后 List.map f 生成一个列表列表。所以 List.concat 将其折叠成一个列表。

List.concat (List.map f xs)

这是一件很常见的事情。