2012-12-17 49 views
2

考慮下面的代碼的理解推理...識別聯合

type TypeOne() = 
    member val Name = "" with get, set 

type TypeTwo() = 
    member val Name = "" with get, set 
    member val Property = 0 with get, set 

[<RequireQualifiedAccess>] 
type UnionType = 
    | TypeOne of TypeOne 
    | TypeTwo of TypeTwo 

// this only succeeds because we have defined the union type a 
// requiring qualified access. otherwise TypeOne would be inferred 
// as the union case, not the type (understandably)... 

let t1 = TypeOne() 

// if we want t1 "as" the union type, we have to do the following... 

let ut1 = UnionType.TypeOne t1 

// the following function returns a result of type UnionType 
// but we have to explicitly do this for each type 

let makeUnion switch = 
    match switch with 
     | true -> UnionType.TypeOne (TypeOne()) 
     | _ -> UnionType.TypeTwo (TypeTwo()) 

正如評論,好像沒有推斷返回的結果應該是聯合型的方式,如果我們有需要對聯合類型進行限定訪問,這非常冗長(這似乎令人擔憂是錯誤的)。

但也沒有建立一個功能只有採取聯合類型,並返回它們作爲工會的方式。 (在這種情況下一個函數,它接受一個TypeOne或TypeTwo並返回UnionType)。或者在那裏?有沒有更好的方式與受歧視的工會合作?

回答

2

由於墊所指出的那樣 - 你不需要資格工會的情況下與其父類型 - 所以你可以寫

let makeUnion switch = 
    match switch with 
    | true -> TypeOne (new TypeOne()) 
    | false -> TypeTwo (new TypeTwo()) 

但是你將永遠有指定TypeOne。這是爲了避免歧義,如果現在你有采取同樣的參數多的情況下 - 就像

type foo= 
|Bar of int 
|Baz of int 

然後甚至不知道返回類型,編譯器不能工作了什麼回來。一個更常見的例子實際上是不帶任何參數的情況 - 比如說你決定重寫true和false:

type bool = |True |False 
+0

是的,這說明了我的理解,謝謝。我沒有,當然做的明顯的事情是類型構造,其作爲墊指出的是一個提示類型檢查的「新」。謝謝! – kolektiv

+0

嗯,你不能在杜的情況下使用較低的情況下。而且,「true」和「false」是不能被重寫的關鍵字。 – pad

+0

@pad - 感謝 - 固定 –

2
type TypeOne() = 
    member val Name = "" with get, set 

type TypeTwo() = 
    member val Name = "" with get, set 
    member val Property = 0 with get, set 

type UnionType = 
    | TypeOne of TypeOne 
    | TypeTwo of TypeTwo 

/// You can give some hints to the type checker 
/// by saying that you want a class constructor 
let t1 = new TypeOne() 

/// No need to use fully-qualified access on union types 
let ut1 = TypeOne t1 

let makeUnion switch = 
    match switch with 
    | true -> TypeOne (new TypeOne()) 
    | false -> TypeTwo (new TypeTwo())