Types Init使用单个构造函数对不同数据类型进行区分的并集
假设我有一种类型,例如:Types Init使用单个构造函数对不同数据类型进行区分的并集,types,f#,discriminated-union,Types,F#,Discriminated Union,假设我有一种类型,例如: type Variedvalue = I of int| S of string | F of float 有没有办法创建一个函数,该函数接受一个泛型参数来初始化union的正确字段 i、 e差不多 with static member initVariedValue (x : 'a) = match x.getType() with | int -> VariedValue.I x | float -> VariedValue.
type Variedvalue = I of int| S of string | F of float
有没有办法创建一个函数,该函数接受一个泛型参数来初始化union的正确字段
i、 e差不多
with static member initVariedValue (x : 'a) =
match x.getType() with
| int -> VariedValue.I x
| float -> VariedValue.F x
| String -> VariedVAlue.S x
这不起作用,即使我内联它,因为在这种情况下,泛型变量被推断为int,因此永远不会到达浮点或字符串条件。
那么,有什么聪明的方法可以做到这一点,还是我只需要为每个字段创建一个构造函数?是的,您可以这样做。但是,当意外类型被传递到构造函数中时,您需要支持这种情况。我会通过返回
结果I |>Ok来实现这一点
| :? 字符串形式为s->s s |>Ok
| :? 浮动为f->f |>Ok
|->Error VariedValue.init 3;;
[]
val it:结果=正常(I 3)
>VariedValue.init是的,您可以这样做。但是,当意外类型被传递到构造函数中时,您需要支持这种情况。我会通过返回结果I |>Ok来实现这一点
| :? 字符串形式为s->s s |>Ok
| :? 浮动为f->f |>Ok
|->Error VariedValue.init 3;;
[]
val it:结果=正常(I 3)
>VariedValue.init可能与我现在没有时间给出完整的答案,但简而言之,F#type系统不允许你做你想做的事情。与类型系统对抗通常会适得其反(而且通常是不可能的);相反,找出你真正想要做的事情,并找到一种实现的方法。另外,当您提到为每个字段创建构造函数时,您是否知道I
、S
和F
都是构造函数?试试看。将您的VariedValue
定义粘贴到F#Interactive中,然后键入F
,你会看到F
是一个类型为float->VariedValue
的函数。我现在没有时间给出完整的答案,但简而言之,F#type系统不允许你做你想做的事情。与类型系统对抗通常会适得其反(而且通常是不可能的);相反,找出你真正想要做的事情,并找到一种实现的方法。另外,当您提到为每个字段创建构造函数时,您是否知道I
、S
和F
都是构造函数?试试看。将您的VariedValue
定义粘贴到F#Interactive中,然后键入F
,您将看到F
是类型为float->VariedValue
的函数。
type VariedValue = I of int| S of string | F of float
module VariedValue =
let init (x: 'a) =
match box x with
| :? int as i -> I i |> Ok
| :? string as s -> S s |> Ok
| :? float as f -> F f |> Ok
| _ -> Error <| sprintf "Unsupported VariedValue Type: %s" (x.GetType().Name)
> VariedValue.init 3;;
[<Struct>]
val it : Result<VariedValue,string> = Ok (I 3)
> VariedValue.init <| System.Guid.NewGuid();;
[<Struct>]
val it : Result<VariedValue,string> =
Error "Unsupported VariedValue Type: Guid"