2015-09-27 83 views
1

我有類似下面需要的情況下,使用靜態解析類型參數:如何把它變成靜態解析類型參數

[<Struct>] 
type Wrapper<'T> = 
    val raw:'T 
    new(v:'T) = {raw = v} 


type Value = 
    | Float of float 
    | Int of int 
    | String of string 

    with 

    member this.ToWrapper() :'T = 
     match this with 
     | Float f -> Wrapper<float>(f)  // type is inferred as float 
     | Int i -> Wrapper<int>(i)   // error 
     | String s -> Wrapper<string>(s) // error 

如何定義和使用ToWrapper功能(或其設置)可以將'Value'類型映射到Generic Wrapper中的任何類型,我知道'T'將是float | int |串?

包裝<'T>類型需要是一個結構,所以接口不是一個選項 - 正如一些其他職位相關的建議。

+0

在這裏使用靜態解析類型參數有什麼意義?是否僅僅使用其中一種類型進行約束? – Gustavo

回答

5

我不清楚你想達到什麼目的。你是否試圖將包裝類型限制爲Int,String和Float?

1)如果是這樣,你可以像這樣在運行時檢查:

[<Struct>] 
type Wrapper<'T> = 
    val raw:'T 
    new(v:'T) = {raw = v} 

let wrap x = 
    match box x with 
    | :? float ->() 
    | :? int ->() 
    | :? string ->() 
    | _ -> failwith "invalid type" 
    Wrapper x 

let a = wrap 90 
let b = wrap "hi" 
let c = wrap true // fails at runtime 

2)如果你想在編譯時限制一個簡單的方法是靜態成員添加爲構造函數:

[<Struct>] 
type Wrapper<'T> = 
    val raw:'T 
    private new(v:'T) = {raw = v} 
with 
    static member wrap (x:float) = Wrapper x 
    static member wrap (x:int) = Wrapper x 
    static member wrap (x:string) = Wrapper x 

let a = Wrapper<_>.wrap 90 
let b = Wrapper<_>.wrap "hi" 
let c = Wrapper<_>.wrap true // doesn't compile 

3),或者可以使用DU包裝內更有意義給你:

type Value = 
    | Float of float 
    | Int of int 
    | String of string 

[<Struct>] 
type Wrapper = 
    val raw:Value 
    new(v:Value) = {raw = v} 

所有溶膠utions 3)是唯一一個真正限制你的包裝的人。解決方案1)和2)限制你構建它的方式。

從2)你可以使用一些具有靜態解析類型參數的技巧來創建一個只包含在這些類型上的內聯函數(不是方法)。儘管如此,這並不會限制類型本身,但由於構造函數是私有的,因此消耗類型的代碼將被強制通過受限制的構造函數。

靜態解析的類型參數可以使用函數或方法,但不能用於類型,因爲它們是編譯時的F#特性,而不是.NET類型的系統特性。

2

您不能這樣做,因爲Wrapper<float>Wrapper<int>(與Wrapper<string>的類型不同)的類型不同。退貨類型ToWrapper是什麼?它不能一次全部三個。