Dictionary 尝试返回映射的元组时无法理解错误

Dictionary 尝试返回映射的元组时无法理解错误,dictionary,tuples,ocaml,Dictionary,Tuples,Ocaml,首先,我有这些类型: type position = float * float type node = position 我编写了这些模块来制作我的地图: module MyMap = struct type t = Graph.node let compare (a1,b1) (a2,b2) = if a1 > a2 then 1 else if a1 < a2 then -1 else if b1 > b2 t

首先,我有这些类型:

type position = float * float
type node = position
我编写了这些模块来制作我的地图:

module MyMap =
  struct
    type t = Graph.node
    let compare (a1,b1) (a2,b2) =
      if a1 > a2 then 1
       else if a1 < a2 then -1
       else if b1 > b2 then 1
       else if b1 < b2 then -1
       else 0
  end

module DistMap = Map.Make(MyMap)
extract\u float(dist n1 n2)
返回从
n1
n2
节点之间的距离提取的浮点值

为了进一步说明,dMap是一个应该像这样构建的映射(node,float),而prevMap是一个应该像这样构建的映射:(node,node)

我在这里的目标是能够返回映射的元组,修改或不修改,这取决于if语句,但这是我得到的错误输出:

Error: This expression has type 'a but an expression was expected of type
         'a DistMap.t -> 'a DistMap.t
       The type variable 'a occurs inside 'a DistMap.t -> 'a DistMap.t
更新:

dist2
函数的类型为
distance

type distance = Distance of float
这里是
提取\u float

let extract_float dist =
  match dist with
    | Distance x -> x
这是我第一次看到这个错误,不管怎样解决这个问题


谢谢。

处理类型错误的第一步是尝试恢复一些上下文类型信息

这里,typechecker正在报告的prevMap部分上的错误

else dMap,prevMap
错误:此表达式的类型为“a”,但表达式的类型应为 'a DistMap.t->'a DistMap.t

类型变量'a出现在'a DistMap.t->'a DistMap.t内

此外,错误是元组第二个元素的预期类型与实际类型不匹配。由于我们正在键入一个
else
分支,这意味着错误开始于
then
分支,只是在稍后引发了冲突。因此,让我们看看
然后
分支(我们现在可以忽略消息的
递归出现部分
):

由于错误是针对元组的第二个元素提出的,因此我们可以将错误的可能根缩小到

 DistMap.add n1 prevMap
此时,我们可以询问DistMap的类型

node -> 'data -> 'data DistMap.t -> 'data DistMap.t
换句话说,从这里第一次使用
prevMap
,我们和typechecker可以推断:

  • prevMap是存储在
    DistMap.t
  • 元组的第二个元素是将
    prevMap
    添加到
    DistMap.t
在这一点上,一切都很好,但随后

else dMap, prevMap
我们了解到,
prevMap
也是一个函数。因此
prevMap
既是
'a DistMap.t
中的一些数据
'a
,也是类型为
'a DistMap.t->'a DistMap.t
的更新函数。这两种类型不兼容(如果不允许递归类型)。因此,错误消息的第一部分是

错误:此表达式的类型为“a”,但表达式的类型应为“a DistMap.t->”a DistMap.t

但是,错误消息的第二部分呢:

类型变量'a出现在'a DistMap.t->'a DistMap.t内

碰巧,
OCaml
可以使这两种类型与
-rectypes
选项兼容,那么
prevMap
的类型是:

'a DistMap.t -> 'a DistMap.t as 'a
这意味着
prevMap
是一个转换
DistMap.t
的函数,其中包含转换
DistMap.t
的函数,其中包含


这种递归类型很少使用,使用时可以掩盖常见的编程错误。因此,它们在默认情况下被禁用,当禁用了
-rectype
时,类型检查器在推断递归类型时会引发一条
递归出现
消息

提取浮点数中的距离是多少?在代码中,您使用的是dist2而不是dist。此外,错误的确切位置是哪里?@PierreG。我会更新我的帖子。谢谢你的长篇大论的回答,帮助我理解这个问题的本质。用OCaml编写代码才几个月,您有什么建议吗?将此函数一分为二以分别更新映射?很可能您想在
然后
分支中更新映射,但错过了要在
n1
键添加的值。我错了吗?天哪。。。是的,就是这样。我忘了放钥匙了。。。真对不起,伙计。谢谢
else dMap, prevMap
'a DistMap.t -> 'a DistMap.t as 'a