【问题标题】:How to turn this into statically resolved type parameters如何将其转换为静态解析的类型参数
【发布时间】:2015-12-24 21:31:55
【问题描述】:

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

[<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 函数(或其集合),该函数可以将“值”类型映射到 Generic Wrapper 中的任何类型,我知道 'T 将是 float |整数 |字符串?

Wrapper 类型必须是 Struct,因此接口不是一个选项 - 正如与此相关的其他一些帖子中所建议的那样。

【问题讨论】:

  • 这里使用静态解析的类型参数有什么意义?仅限制使用其中一种类型吗?

标签: f#


【解决方案1】:

我不清楚你想达到什么目标。您是否试图将包装类型限制为 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}

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

从 2) 开始,您可以对静态解析的类型参数使用一些技巧,以便提出仅包含这些类型的内联函数(不是方法)。这仍然不会限制类型本身,但由于构造函数是私有的,因此使用您的类型的代码将被强制通过您的受限构造函数。

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

【讨论】:

    【解决方案2】:

    您不能这样做,因为Wrapper&lt;float&gt;Wrapper&lt;int&gt; 的类型不同(与Wrapper&lt;string&gt; 的类型也不同)。 ToWrapper 的返回类型是什么?不能同时三个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多