开发者

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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜