关于SML类型ckecking和推理的问题

时间:2017-06-12 00:50:45

标签: sml type-inference typechecking

首先,由于问题与学校项目有某种关系,我不认为发布我的代码是合适的。另外,正如我稍后解释的那样,我只对相关代码进行了修改。

我解释自己。我应该使用优先级队列来实现Dijkstra算法的一个版本。我认为这样做的一个简单的功能方法是定义一个dijkstra函数,其中输入队列和目标节点,以及一个帮助函数,用于将与刚刚出列的列表元素相邻的节点入队。不幸的是,帮助函数确实没有进行类型检查 - 未解决的Flex记录。

到目前为止,似乎代码很重要,但允许我再添加一个 详情。由于图是4-canonical(意味着每个节点恰好有四个邻居),我使用模运算将其表示为矩阵。为了简化我的算法,我使用这个事实来重写它并使用4个额外的辅助函数 - 每个移动一个可能 - 而不是第一个辅助函数内的四个ifs。如果我们应该访问这个节点(这意味着我们将需要的成本小于当前所需的成本),则四个移动函数中的每一个都返回true,否则返回false。第一个帮助器只返回一个包含四个布尔变量的元组。最后,我复制了在我第一次尝试进入dijkstra代码体时没有工作的入队代码,突然间它做了类型检查。

我知道它可能仍然不清楚,也许你只能猜测发生了什么。但我真的很困惑。我也搜索了这个网站和SML基础,发现在下列情况下会发生这种错误:

f(x,y,z)= ...

其中z未被使用,因此检查员无法扣除它是什么。 我确信在我的问题中并非如此,因为我只是复制粘贴代码(不是我知道的非常好的技术,但确定)。因此,我得出结论,问题是类型检查器没有使用函数调用。我再次搜索并找到了Hindley Miller算法的解释。并且从我每次遇到的理解和功能将假设是a-> b作为第一步,稍后将进入函数的定义并完成任务。所以我回到原点并决定在这里提出这个问题,寻求更好地理解类型推断或者暗示已经发生的事情。

P.S。 1)即使我尽力解释这个问题我仍然不清楚或太宽泛让我知道,我会删除,没问题。 附: 2)一个更小更简单的问题:我读到#1不建议采用元组的第一个元素,有时候它甚至不能进行类型检查 而应该使用模式匹配。你能解释一下吗? 附: 3)有人可能想知道为什么我问这个问题,因为我第二次尝试解决了这个问题。就个人而言,我不会考虑解决但隐藏。

提前致谢并对问题的大小表示抱歉。

链接:

SML/NJ Errors

P.S. 2)

Hindley-Miller

更新:经过一些额外的搜索,我猜到了什么是错的。我正在实现一个不是为我的问题定制的优先级队列,但更一般。因此,当我第一次将一个元素排入队列时,优先级队列类型的推断正在发生。但是在排队我的源节点并调用dijkstra之后,队列将再次变为空(我的dijsktra将第一个元素排队,检查它是否是目标节点)并且第一次调用辅助函数添加节点将具有空队列作为一个它的论点。也许空队列没有类型,导致错误?

1 个答案:

答案 0 :(得分:1)

我猜你在问什么。

  

我有一个函数enqueue在一个上下文中不起作用,但它在另一个上下文中起作用。为什么?它使用#1宏,并且我读到#1不建议采用元组的第一个元素,有时它甚至没有进行类型检查,而应该使用模式匹配。

在标准ML中,#1是一个宏。它的行为类似于函数,但与函数不同,它对于任何带有 1 字段的元组/记录都会重载。如果您没有指定要传递给函数的元组类型,则使用#1将不会消除歧义。例如,

- fun f pair = #1 pair;
! Toplevel input:
! fun f pair = #1 pair;
!              ^^
! Unresolved record pattern

但是给它类型(通过显式类型注释,或者在可以通过其他方式推断类型的上下文中)效果很好。

- fun f (pair : int * int) = #1 pair;
> val f = fn : int * int -> int

我不知道我是否将#1标记为明确的禁止和模式匹配作为唯一选项, [edit:... 但是{{3} IonuţG。Stan所链接的有一些论点。]

两者都有优点和缺点。或者,您可以制作明确的getter,它只适用于您正在使用的元组类型。例如,

fun fst (x, _) = x
fun snd (_, y) = y