F# Quotations - traversing into function calls represented by a Value

前端 未结 1 1449
长发绾君心
长发绾君心 2020-12-10 20:50

I\'ve spent a few hours trying to get to grips with F# Quotations, but I\'ve come across a bit of a road block. My requirement is to take simple functions (just integers,+,-

相关标签:
1条回答
  • 2020-12-10 21:33

    Quotations represent the F# code that was quoted syntactically. This means that if you write something like <@ x @>, the quotation will contain just Value case specifying that you quoted something which has the specified value. (Variables are automatically replaced with values if the variable is defined outside of the quotation).

    You can only get quotation of code that was explicitly quoted using <@ .. @> or of a function that was marked as ReflectedDefinition and is referred to by name in a quotation (e.g. <@ add @> but not for example let f = add in <@ f @>).

    To be able to do what your snippet suggests, you'll need to store quotations in your FuncType too (so that the lambda function that you write is also quoted and you can get its body). Something like:

    type FuncType = 
      | A of Expr<int -> int -> int>
      | B | C
    
    [<ReflectedDefinition>]
    let add x y = x + y
    
    let myFunc1 = A <@ fun x y -> x + y @>
    let myFunc2 = A <@ add @>
    
    let thefunc expr = 
        match expr with
        | A(x) -> x
        | _ -> failwith "fail"
    

    This should work for functions marked as ReflectedDefinition too. To extract the body of the function you need to add something like (you'll need to substitute arguments of the function for parameters, but this should give you some idea):

    match expr with
    | Lambdas(_, body) -> 
        match body with 
        | Call(_, mi, _) when Expr.TryGetReflectedDefinition(mi) <> None ->
          let func = Expr.TryGetReflectedDefinition(mi)
          match func with 
          | Some(Lambdas(_, body)) ->
              // 'body' is the quotation of the body
          | _ -> failwith "Not supported function"
        | _ -> failwith "Not supported function"
    | _ -> failwith "Not supported expression"
    
    0 讨论(0)
提交回复
热议问题