我试图访问上级模块中定义的类型:
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;
我能够使用命名空间来实现我想要的功能,但是可以使用模块来实现吗?
答案 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 }