【问题标题】:Why do Record types oblige you to define its members types?为什么记录类型要求您定义其成员类型?
【发布时间】:2011-11-03 07:49:21
【问题描述】:

似乎记录类型要求您声明其成员类型:

type Point = { X:int; Y:int }

它背后的基本原理是(或可能是)什么?

似乎在 F# 中,您可以(几乎)总是在编码时不必定义类型。这让我觉得,这种限制或许有很强的理论基础。是这样吗?

对罗伯特的回应:

我确实理解您的担忧,但在我看来,这似乎是错误的推理。我们来看一个例子:

假设 F# 允许我们定义无类型成员:

type Point = { X; Y; }

您的推理围绕着这样一个事实,人们可以在我们的代码中找到如下内容:

let a = { X=1; y=2 } //(1)
let b = { X="1"; y="2" } //(2)

既然如此,编译器别无选择,只能将Point 定义为(隐式)

type Point = { X:object; Y:object }

现在,您可能不仅要创建记录,还要使用它们。话虽如此,您的代码中可能会有一些地方尝试将 Point 的成员视为整数:

let z = a.X + 2 //ERROR. goes against what is seen in (2)

以及其他您将它们视为字符串的地方:

let w = A.X + "abc" //ERROR. goes against what is seen in (1)

两者都会标记错误,因此即使尝试对记录的成员使用相互不兼容的类型,您也做不到!它们会在某种程度上兼容吗?F# 会发现我们使用的可能不是通用的根类型。

这里的明智之处在于与您所描述的相反

您是否希望字段在移动时突然改变其类型 从一条记录到另一条记录?

从一条记录移动到另一条记录时,记录类型不会更改。在更坏的情况下,可能会发生的情况是 Record 的成员类型将非常通用(更糟糕的是,来自 Object 类型)。

但是,当你编写一个只接受无类型参数的方法时,这与你所冒的风险完全相同!正如我们所知,这在 F# 中是允许的。

所以,除非我在这里遗漏了什么,否则这可能不是您必须在 Records 中定义类型的原因。

【问题讨论】:

  • 我认为对您的更新的简短回答归结为“结构比较”,Thomas Petricek 在他的一些材料中提到了这一点。您的场景假定编译器通过该记录的第一个实例推断每个“点”record 的类型,我很确定 F# 编译器不会这样做。
  • 我相信我确实在他的一篇关于 SO 的帖子中听说过“结构比较”。但我必须阅读它,因为我对此一无所知。
  • 很简单,Thomas 指出的是,记录就像 c# 中的类,元组就像匿名类型。在类中为每个成员指定类型是合理的,或者在在类型级别(而不是在实例级别,这将是运行时绑定)静态推断该类型。
  • 不幸的是,他没有在材料中说明我读到的确切原因,他们决定要求输入记录。我可以想象它使编译器的工作变得更容易。

标签: .net f# functional-programming record


【解决方案1】:

如果 F# 允许您定义无类型记录,那么它更有可能将它们解释为具有通用类型字段的记录(而不是像您在编辑中那样使用 object)。所以假设:

type Point = { X; Y }

其实意思是:

type Point<'T1, 'T2> = { X : 'T1; Y : 'T2 }

现在你可以写{ X = 1; Y = 2 }{ X = "foo"; Y = new System.Random() }。然而,这只是让记录没那么有用。记录应该以两种方式记录值的含义:1)通过标记字段和 2)通过指定字段类型。使用您建议的功能,您将删除 (2)。

当然,如果您有一个通用记录,您仍然可以明确定义它(并将其与不同的值一起使用),但自动执行此操作可能不会很有帮助。

【讨论】:

    【解决方案2】:

    我认为这里有些混乱。 F# 是一种静态类型语言。 F# 编译器不会生成任何无法确定类型的代码。

    但这与编写方法时所冒的风险完全相同 只需要无类型参数!正如我们所知,这是允许的 在 F# 中。

    没有没有类型参数的函数。函数的每个参数都有一个类型,无论是普通类型,如 int、float 还是泛型类型。如果您不为参数提供类型,这并不意味着参数较少,编译器将根据参数的使用方式推断类型,如果在某些情况下无法推断类型,则会引发编译器错误。

    【讨论】:

    • 当我提到无类型参数时,我的意思是您不必键入它们。我知道编译器将确定他们可能拥有的最通用的类​​型。如果您阅读整个 OP,您会看到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2020-08-21
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多