如何编写参数类型而不是类型值的函数?

时间:2010-03-16 13:16:23

标签: f# types

我想将几十个枚举类型的字符串表示转换为枚举值。 将字符串转换为具体类型很容易:

Enum.Parse(typeof<FontStyle>,"Bold") |> unbox<FontStyle>

但是现在我想写函数,其中type和string是参数。 我能写的最好的是:

> let s2e (_: 'a) s = Enum.Parse(typeof<'a>,s) |> unbox<'a>;;
val s2e : 'a -> string -> 'a
> s2e FontStyle.Regular "Bold";;
val it : FontStyle = Bold

有没有选择写这样的东西但是将类型本身作为第一个参数?

2 个答案:

答案 0 :(得分:4)

该函数需要采用单个类型参数,该参数将是返回的枚举的类型。但是,您不需要使用代码中未使用的“伪”参数来指定类型 - 您可以使用相同的表示法调用函数时指定实际的类型参数,例如在调用{{1 }}。

以下修改的函数采用仅在返回类型中出现的单个类型参数(为了避免混淆SO代码格式化程序,我在代码中替换了'with':

defaultof<SomeType>

调用函数时,需要明确指定类型:

> let parseEnum<´a> s = Enum.Parse(typeof<´a>,s) |> unbox<´a>;; 
val parseEnum : string -> ´a

您的解决方案与此非常接近 - 唯一的变化是您可以显式指定类型参数,而不是提供见证值来指导类型推断。

答案 1 :(得分:1)

托马斯的回答很好。另外,请注意您可以应用F#的enum约束来防止使用无意义的类型参数:

let parseEnum<'t,'u when 't:enum<'u>> s = System.Enum.Parse(typeof<'t>, s) :?> 't
(parseEnum "Class" : System.AttributeTargets)

现在调用(parseEnum "Test" : int)将在编译时失败,因为int不是枚举。

修改

由于我们实际上没有对基础类型'u执行任何操作,因此我们不需要F#的枚举约束的全部功能,因为ssp在注释中指出。这更容易使用,因为它只有一个类型参数:

let parseEnum<'t when 't :> System.Enum and 't : struct> s =
  System.Enum.Parse(typeof<'t>, s) :?> 't

请注意,struct约束会阻止使用System.Enum本身作为类型参数。