如何将其转换为静态解析的类型参数

Sam*_*Sam 1 f#

我需要在类似下面的情况下使用静态解析的类型参数:

[<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
Run Code Online (Sandbox Code Playgroud)

如何定义和使用ToWrapper函数(或其设置),它可以将'Value'类型映射到Generic Wrapper <'T>中的任何类型,我知道'T将浮动| int | 串?

Wrapper <'T>类型需要是一个Struct,因此接口不是一个选项 - 正如在与此相关的其他一些帖子中所建议的那样.

Gus*_*Gus 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

3)或者可能是,使用包装内的DU对你来说更有意义:

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

[<Struct>]
type Wrapper = 
    val raw:Value
    new(v:Value) = {raw = v}
Run Code Online (Sandbox Code Playgroud)

在所有解决方案中,3)是唯一真正限制你的包装的解决方案.解决方案1)和2)限制您构建它的方式.

从2)你可以使用一些具有静态解析类型参数的技巧,以便提出一个仅包装在那些类型上的内联函数(不是方法).仍然不会限制类型本身,但由于构造函数是私有的,因此使用类型的代码将被强制通过受限制的构造函数.

静态解析的类型参数适用于函数或方法,但不适用于类型,因为它们是编译时F#特性,而不是.NET类型系统特性.