F#在阴影记录类型

时间:2017-04-22 11:50:31

标签: .net f# functional-programming record

我有两种具有相同签名的记录类型:

type T1 = { a : int }
type T2 = { a : int }

let badFunc record = { record with a = 0 }
let goodFunc (record : T2) = { record with a = 0 }

编译器将在badFunc函数中发出警告:

  

此记录表达式或模式的字段标签和预期类型不能唯一地确定相应的记录。

来自F# RFC FS-1025 - Improve record type inference

  

在解析记录类型时,编译器的当前行为是为记录类型的每个字段查找具有该字段的范围内的所有类型。然后它为所有字段采用这些类型的交集,如果找到单个匹配类型,则选择该类型。否则,盲目选择列表中的第一个类型,然后就会出现错误。

所以F#应该知道badFunc类型是T2 -> T2,为什么F#会忽略阴影并发出警告?

1 个答案:

答案 0 :(得分:4)

如评论中所述,记录T1不会记录T2。我可以看到这种推理可能来自何处,因为这是变量阴影的工作原理:

let foo () =
  let a1 = 10
  let a1 = 20
  a1

这里,a1的第二个声明隐藏了第一个声明。对于记录,您可能希望具有相同名称的记录将隐藏先前的声明:

type T1 = { a : int }
type T1 = { a : int }

但是,这不起作用,并且您收到错误消息:

  

错误FS0037:类型,例外或模块的重复定义' T1'

在您的定义中,您定义了两个单独的类型T1T2,它们碰巧具有相同的字段。您始终可以使用完全限定语法来引用该字段:

let t1Func record = { record with T1.a = 0 }
let t2Func record = { record with T2.a = 0 }

编写a时编译器应该怎么做?这是一个设计决策 - 它可以自动选择其中一个,但这通常有点令人困惑,因为它可能取决于您打开命名空间的顺序。因此,正如编译器当前所做的那样,发出警告可能是更明智的方法。