如何在嵌套作用域中引用同名的类型

时间:2016-11-02 21:20:28

标签: f#

我试图访问上级模块中定义的类型:

module MainModule

type Data = { stuff }

module XmlDeserialization =
    type Data() =
       [<XmlAttribute("stuff")>]
       member val stuff ...

       member x.ToDomainType() =
           {
               stuff = x.stuff
           } : MainModule.Data

问题是,最后一行没有编译,因为&#34;类型&#39; MainModule&#39;没有定义。&#34;

我能够使用命名空间来实现我想要的功能,但是可以使用模块来实现吗?

2 个答案:

答案 0 :(得分:5)

您无法在MainModule本身的正文中引用MainModule,因为此时,模块在技术上尚未定义。这可以通过较小的程序重现:

module M =

  type T = T
  let x: T = T    // OK
  let y: M.T = T  // Error: module M is not defined yet

最简单的解决方案是在开始定义MainModule之前完成XmlDeserialization的定义:

module MainModule =

    type Data = { stuff }

module XmlDeserialization =
    type Data() =
       [<XmlAttribute("stuff")>]
       member val stuff ...

       member x.ToDomainType() =
           {
               stuff = x.stuff
           } : MainModule.Data  // Works now

但如果您坚持XmlDeserialization嵌套在MainModule下,您坚持认为类型必须具有相同的名称,那么您可以通过以下方式处理类型阴影:在定义黯然失色之前创建原始类型的别名:

module XmlDeserialization =

    // Alias the original type
    type MainModule_Data = Data

    type Data() =
       [<XmlAttribute("stuff")>]
       member val stuff ...

       member x.ToDomainType() =
           {
               stuff = x.stuff
           } : MainModule_Data  // Refer by alias: works now

答案 1 :(得分:4)

在这种特定情况下,如果删除类型注释,它应该可以正常工作。编译器将从记录Data的字段中推断出记录类型。

通常,您可以声明一个函数来强制执行给定的记录类型,例如:

let private mainModuleData (instance : Data) = instance

如果在Data被遮蔽之前定义了此函数,即使记录字段不明确,您也可以使用该函数强制执行正确的类型:

   member x.ToDomainType() =
       mainModuleData
        { stuff = x.stuff }