F# - Extract option from Expr
Is there a way to extract a parameter from an Expr
?
An examp开发者_开发百科le:
let hasStringOption (e:Expr<string option>) =
let myOption : string option = ..some code to get the string option from e
How would I get the string option
inside the Expr
and assign it to myOption
?
In your example, string option
represents the expression return type, so the expression itself could be arbitrarily complex and requires some kind of evaluation strategy like the PowerPack's as @wmeyer has shown.
But if you actually have a string option
expression you can use the standard library quotation active patterns and reflection to implement your own evaluation strategy (generic option shown here):
module P = Microsoft.FSharp.Quotations.Patterns
let extract (expr:Expr<'a option>) =
match expr with
| P.NewUnionCase (uci, args) ->
if uci.Name = "Some" then
match args.Head with
| P.Value(value, ty) -> Some(value :?> 'a)
else
None:('a option)
let example1 = extract <@ None:int option @>
let example2 = extract <@ Some("hello world") @>
and indeed, such an approach may be a piece of your own strategy for recursively evaluating arbitrary expressions using reflection and active patterns rather than PowerPack's slow and limited intermediate LINQ strategy.
With FSharp.PowerPack.Linq.dll
referenced you can do:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let hasStringOption (e:Expr<string option>) =
let myOption : string option = e.Eval()
myOption.IsSome
printfn "%A" (hasStringOption <@ Some "hello" @>)
printfn "%A" (hasStringOption <@ None @>)
However, reportedly this is quite slow and uses LINQ expressions as an intermediary step.
Sadly (or not), you cannot evaluate F# quotations. The F# PowerPack has a limited ability to compile quotations to LINQ expressions (which can be evaluated).
精彩评论