可以用fsharp中的泛型替换GetUnionCases吗?

时间:2014-04-20 13:38:08

标签: generics f# discriminated-union

我有以下功能。它用于将字符串的某些部分转换为Discriminated union情况。我有特定的,并且已经重复和推广代码。

let extractor ty (characters:list<char>)= 
 //find the UnionCaseInfo for the named subtype of Token (ty)
 let uci = (Microsoft.FSharp.Reflection.FSharpType.GetUnionCases(typeof<Token>) |> Array.filter (fun u->u.Name.Equals(ty))).[0]
 //construct the chosen type from the passed in ElementValue (l)
 let maker l = Microsoft.FSharp.Reflection.FSharpValue.MakeUnion(uci,[|l|]) :?> Token
 match characters with
 | '('::t -> match t with
             | '!'::t2  -> match t2 with
                           | '\''::t3 -> let (entries,rest) = t3 |> entriesUntil '\''
                                             (maker(LiteralInsertion(stringOf entries)),trimHeadIf ')' rest)
             | '\''::t2 -> let (entries,rest) = t2 |> entriesUntil '\''
                           (maker(LiteralValue(stringOf entries)),trimHeadIf ')' rest)
             | '$'::t2  -> let (entries,rest) = t2 |> entriesUntil ')'
                           (maker(CaptureValue(stringOf entries)), rest)
             | _ -> failwith "Expecting !'Insertion', $Capture or 'Literal' following ("
 | l      -> (maker(DataCellValue),l)

我想做以下事情:

let extractor<'T> (characters:list<char>) = 
 etc...
 | l -> ('T(DataCellValue),l)

但这没有用(所以我最终采用了反思方法)

事先提前

1 个答案:

答案 0 :(得分:1)

type DU = 
    | A
    | B

let inline create v = (^a : (new : DU -> ^a) v)

type Ty (du: DU) = class end

let ty: Ty = create A

所以,在你的情况下,它可能看起来像这样

type DU1 = 
    | LiteralInsertion
    | DataCellValue

type Token (du: DU1) = class end

let inline extractor ty (characters: list<char>) : 'a = 
    match characters with
    | '(' :: t -> (^a : (new : DU1 -> ^a) LiteralInsertion)
    | l -> (^a : (new : DU1 -> ^a) DataCellValue)

let x: Token = extractor "ty" []

如果没有帮助,请显示完整代码(我的意思是类型令牌和DUs)。