F#命名约定是否禁止在不同光盘中具有相同的名称。工会类型?

时间:2016-05-27 22:24:03

标签: f#

我在一个模块中有一个共同类型,并且该类型在另外两个有区别的联合类型中使用。

为方便起见,我将它们命名为同名。其他名称不同。接下来,我正在尝试制作一个在控制台中打印类型的帮助器。

第一行无法编译,因为匹配大小写中的类型不匹配。我已经尝试了一些东西,无论是否打开模块,强制类型等,它仍然会失败。

另一件事是,如果我将鬃毛更改为Common1和Common2,它的工作没有任何问题。

我记得读过具有相同签名的类型存储在同一内部类型中,但我的真实示例有不同的签名但仍然失败。

我在某个地方错过了一点吗?

示例:

示例无法编译,但出现错误:

错误此表达式应具有类型OneA,但此处具有类型OneB

enter image description here

module commonThings =
    type CommonThing = 
        | Comm1 of int 
        | Comm2 of int 

module thingA =
    open commonThings
    type OneA = 
        | A1 of string
        | Common of CommonThing        
        | A2 of string

module thingB =
    open commonThings
    type OneB = 
        | B1 of string
        | Common of CommonThing        
        | B2 of string

module printAB =
    open commonThings
    open thingA
    open thingB

    let printA (msg:OneA) = 
        match msg with
        | A1 v -> printfn "A1"
        | Common v -> printfn "Common"
        | A2 v -> printfn "A2"

module main =

    [<EntryPoint>]
    let main argv = 
        printfn "%A" argv
        0 // return an integer exit code

2 个答案:

答案 0 :(得分:5)

您可以通过为类型名称添加前缀来消除歧义:

let printA (msg:OneA) = 
    match msg with
    | A1 v -> printfn "A1"
    | OneA.Common v -> printfn "Common"
    | A2 v -> printfn "A2"

答案 1 :(得分:5)

当您打开thingB模块时,键入OneB进入范围,类型Common中的OneA案例标签会被OneB类型的标签遮蔽。

当类型或联合/活动模式案例之间发生名称冲突时,最新的案例会获胜。重新排序打开将使它偶然起作用:

open thingB
open thingA

正确的解决方案是在案例名称前加上前缀。您还可以使用RequireQualifiedAccess属性强制类型(或模块)始终需要其内部的前缀。