我的程序有一些记录类型具有相同的字段名(每个记录类型意味着不同的东西)。 编译器坚持功能参数此记录形状相匹配,必须声明的最后一个类型的,即使我宣布创纪录的情况下,有明确的字段名称,并且总是传递一致的类型到每个功能。
什么是适当的方式来处理这件事? 我知道我可以把一个类型的注释中的功能,但我觉得如果我做事情的方法不对,我不应该需要与类型注释打架编译器。
最小代码演示问题:
type type1 = {x:int}
type type2 = {x:int}
let getX t =
t.x
getX {type1.x=1}
|> ignore
编译器输出:
$ fsharpc --nologo test.fs
/tmp/typetest/test.fs(7,6): error FS0001: This expression was expected to have type
type2
but here has type
type1
大约有这几个方面:
类型标注为你的建议:
let getX (t : type1) = tx
限定getX
冲突类型定义之前:
type type1 = {x:int} let getX t = tx type type2 = {x:int}
没有明确指定调用函数时的类型:
getX {x=1}
其中的这些选项是“正确”的方式取决于精确的情况很多。
除了由PSWG答案,你可能会考虑使用模块划分的范围。
module A =
type type1 = {x:int}
module B =
type type2 = {x:int}
module C =
// only make type1 visible in C
open A
let getX t =
t.x
getX {type1.x=1}
|> ignore
我要说的是,在F#中,具有相同的命名空间两个记录具有相同的标签是有点代码味道的。
你可以使用一个约束上getX
:
let inline getX (t: ^T) =
(^T : (member x: int) (t))
然而试图使其更通用的(而不是要求物业x
是int
):
let inline getX_generic (t: ^T) : 'U =
(^T : (member x : 'U) (t))
具有与F#解释器,编译器和运行的问题。
在F#解释炸弹出来,编译器认为getX_generic
返回obj
,而不是int
,当你这样做运行它,它不计算。
F#是一种新语言有一些错误 - 如果你想这样的工作 - 我建议你在一个bug报告中记录这些问题。
文章来源: Compiler can't tell which record type with duplicate fields should be the function parameter type