似乎记录类型要求您声明其成员类型:
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#允许这样做。
所以,除非我在这里遗漏了一些东西,否则这可能不是你 在记录中定义类型的原因。
答案 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还是泛型类型。如果你不为参数提供类型并不意味着参数更少,编译器将根据参数的使用方式推断类型,如果在某些情况下它无法推断它将抛出编译器错误的类型。