0

I have the following function. It is used to turn parts of a string into a Discriminated union case. I had specific ones and have been deduping and generalising the code.

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)

I would like to do something like the following:

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

but that didn't work (so I ended up with the reflection approach)

thx in advance

CodeBeard
  • 515
  • 3
  • 10

1 Answers1

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

So, in your case it may look like this

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

If it does not help, please show full code (I mean types Token and the DUs).

  • Thanks, I can't see how I can apply this in my case. My failing. But my brain is stuck at the `extractor` level. I would like a function that returns a given type with a controlled insertion of a different type (both DUs). I would like the calling code to be like this `extractor characters`. – CodeBeard Apr 20 '14 at 15:56
  • Vasily, that helps: thanks. I am going to have to give it a go in context to see if I really understand it. It appears to still work on a string name rather than a generic. Do you think a generic is not possible? – CodeBeard Apr 21 '14 at 07:00