SML型校验与推理问题

SML型校验与推理问题,sml,type-inference,typechecking,Sml,Type Inference,Typechecking,首先,由于这个问题与学校的一个项目有关,我认为发布我的代码是不合适的。另外,正如我稍后解释的,我只有一个修改版本的代码 我解释我自己。我应该使用优先级队列实现Dijkstra算法的一个版本。我认为这样做的一个简单的函数方法是定义一个dijkstra函数,其中包含队列和目标节点的输入,以及一个helper函数,用于将与刚刚出列的列表元素相邻的节点排队。不幸的是,helper函数没有对未解析的Flex记录进行类型检查 到目前为止,代码似乎很重要,但请允许我再添加一个 细节因为图是4-正则的,每个节点

首先,由于这个问题与学校的一个项目有关,我认为发布我的代码是不合适的。另外,正如我稍后解释的,我只有一个修改版本的代码

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

到目前为止,代码似乎很重要,但请允许我再添加一个 细节因为图是4-正则的,每个节点正好有四个邻居,所以我使用模运算将其表示为一个矩阵。为了简化我的算法,我用这个事实重写了它,并使用了4个额外的辅助函数——每个移动一个——而不是第一个辅助函数中的4个ifs。如果我们应该访问此节点,则四个移动函数中的每一个都返回true,这意味着我们通过这种方式需要的成本小于当前需要的成本,否则返回false。第一个助手只返回四个布尔变量的元组。最后,我将我第一次尝试时不起作用的排队代码复制到dijkstra代码的主体中,突然它进行了类型检查

我知道这可能还不清楚,也许你只能猜测到底发生了什么。但我确实很困惑,我也搜索了这个网站和SML basis,发现这种错误发生在以下情况:

f x,y,z=

其中z未使用,因此检查者无法扣除它是什么。 我确信我的问题不是这样的,因为我只是复制粘贴代码。我知道这不是一个很好的技术,但还行。因此,我得出结论,问题在于typechecker不能处理函数调用。我又搜索了一遍,找到了欣德利-米勒算法的解释。根据我每次遇到的理解,一个函数将假设是a->b作为第一步,然后将转到函数的定义并完成任务。所以我回到了第一步,决定在这里问这个问题,寻找对类型推断的更好理解,或者寻找发生了什么的线索

p.S.1尽管我尽了最大努力解释我的问题,但仍然不清楚或太宽泛,请让我知道,我将删除,没有问题。 P.S.2一个更小更简单的问题:我读到1不建议取元组的第一个元素,有时甚至不进行类型检查 相反,它应该用于模式匹配。你能解释一下吗? 有人可能会想,既然我第二次尝试解决了这个问题,为什么我会问这个问题。就个人而言,我不认为解决了,而是隐藏了。 提前感谢,并为问题的规模感到抱歉

链接:


更新:经过一些额外的搜索,我有一个关于什么是错误的猜测。我实现的优先级队列不是针对我的问题定制的,而是更一般的。因此,优先级队列类型的推断是在我第一次将一个元素加入队列时发生的。但是,在将源节点加入队列并调用dijkstra之后,队列将变空,因为我的dijsktra再次将第一个元素退出队列,检查它是否是目标节点,并且add nodes的helper函数的第一次调用将有一个空队列作为其参数之一。可能是空队列没有类型,这是导致错误的原因?

我猜你在问什么

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

在标准ML中,1是一个宏。它的行为类似于一个函数,但与函数不同的是,它重载了任何包含1字段的元组/记录。如果不指定传递给函数的元组类型,则使用1不会消除歧义。比如说,

- fun f pair = #1 pair;
! Toplevel input:
! fun f pair = #1 pair;
!              ^^
! Unresolved record pattern
fun fst (x, _) = x
fun snd (_, y) = y
但是,通过显式类型注释或在可以通过其他方式推断类型的上下文中为其指定类型都很有效

- fun f (pair : int * int) = #1 pair;
> val f = fn : int * int -> int
我不知道我是否会将1标记为明确的禁止选项,并将模式匹配作为唯一选项,[编辑:…但IonuțG.Stan链接到的有一些参数。]

两者都有优点和缺点。或者,您可以创建只对正在使用的元组类型有效的明确的getter。比如说,

- fun f pair = #1 pair;
! Toplevel input:
! fun f pair = #1 pair;
!              ^^
! Unresolved record pattern
fun fst (x, _) = x
fun snd (_, y) = y

你的问题是什么?@Simon Shine我的问题是,为什么enqueue在第二个函数中没有键入resolve,而是在Dijkstra内部移动时键入resolve;推理对函数的作用是否不同?或者我理解正确了,可能是别的什么?@cgss这将极大地帮助我们
查看一些正在运行/失败的代码,即使问题比这更一般。此外,您看到这个问题了吗?@久特·G·斯坦,我再次为我的不存在道歉,但我想我可以解释我自己。也许我应该试着写一个伪代码或者类似的东西?你认为这有帮助吗?我也看到了一个问题:是P.S.2链接。我确实帮助我进行了第二次尝试,但正如你可能已经注意到的那样,这并没有解释为什么,这导致我进入了P.S.2,它实际上回答了我的P.S.2小问题,谢谢!我投了赞成票,但不算数。尽管我会要求澄清你提出的一点。让我们假设我们有乐趣f,正如您在开始时定义的那样,没有类型声明,如果检查器说ok,我会知道它是什么,一旦您调用,那么没有限制,如果您希望首先使用2元素元组调用它,然后使用3元素,或者即使您使用整数元组调用它,然后使用字符串元组调用它。现在,因为ML不想让程序员犯这样的错误,它会从一开始就说模式错误?我的字符用完了,你是说不要因为它过载而消除歧义吗?我还应该提到,enqueue没有出现这种情况,而且每个参数都是在添加节点的函数或基本dijkstra函数中使用的。@cgss:对不起,您必须更简洁一些。我不知道你在问什么。关于堆栈溢出的注释不适合后续对话。理想情况下,你应该提出一个简洁的问题,并得到一个简洁的答案,如果有必要,如果你可以具体化的话,更新你的问题。听起来您想了解类型推断在基本层面上是如何工作的。您可能喜欢阅读中链接的文章。您可能想了解重载函数/运算符意味着什么。再一次,我很抱歉,但请允许我再发表一点评论。我阅读了你提供的链接,虽然我认为我对类型推断有一个基本的理解,但它们帮助我更进一步。因此,我将更新我的问题以添加一些新信息。我以前在C++和java中看到过重载,但是除了普通的场合之外,还从来没有用过函数语言。