为什么记录类型要求您定义其成员类型?

时间:2011-08-25 03:11:43

标签: .net f# functional-programming record

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

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#允许这样做。

所以,除非我在这里遗漏了一些东西,否则这可能不是你 在记录中定义类型的原因。

2 个答案:

答案 0 :(得分:7)

如果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)。

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

答案 1 :(得分:1)

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

  

但这与您编写方法时的风险完全相同   只会采取无类型的论点!而且,正如我们所知,这是允许的   在F#。

没有类型少参数的功能。函数的每个参数都有一个类型,无论是普通类型,如int,float还是泛型类型。如果你不为参数提供类型并不意味着参数更少,编译器将根据参数的使用方式推断类型,如果在某些情况下它无法推断它将抛出编译器错误的类型。