编译器不能告诉记录类型重复的领域应该是函数参数类型(Compiler can't tell

2019-10-20 13:50发布

我的程序有一些记录类型具有相同的字段名(每个记录类型意味着不同的东西)。 编译器坚持功能参数此记录形状相匹配,必须声明的最后一个类型的,即使我宣布创纪录的情况下,有明确的字段名称,并且总是传递一致的类型到每个功能。

什么是适当的方式来处理这件事? 我知道我可以把一个类型的注释中的功能,但我觉得如果我做事情的方法不对,我不应该需要与类型注释打架编译器。

最小代码演示问题:

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    

Answer 1:

大约有这几个方面:

  1. 类型标注为你的建议:

     let getX (t : type1) = tx 
  2. 限定getX冲突类型定义之前:

     type type1 = {x:int} let getX t = tx type type2 = {x:int} 
  3. 没有明确指定调用函数时的类型:

     getX {x=1} 

其中的这些选项是“正确”的方式取决于精确的情况很多。



Answer 2:

除了由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#中,具有相同的命名空间两个记录具有相同的标签是有点代码味道的。



Answer 3:

你可以使用一个约束上getX

let inline getX (t: ^T) =
    (^T : (member x: int) (t))

然而试图使其更通用的(而不是要求物业xint ):

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
标签: f# record