0

我有以下功能。它用于将字符串的一部分转换为可区分的联合情况。我有特定的,并且一直在对代码进行重复数据删除和概括。

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)

但这不起作用(所以我最终采用了反射方法)

提前谢谢

4

1 回答 1

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" []

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

于 2014-04-20T15:36:36.713 回答