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,+,-,/,*) out of a discriminated union type and generate an expression tree that will eventually be used to generate C code. I know this is possible using Quotations with 'direct' functions.
My problem is that the expression tree seems to terminate with a "Value", and I can't figure out how to traverse into that value.
My questions is whether this is actually possible in this situation? or are there any other approaches that are worth considering.
type FuncType =
| A of (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"
printfn "%A" (thefunc myFunc1) // prints "Value (<fun:myFunc1@14>)"
printfn "%A" (thefunc myFunc2) // prints "Value (<fun:myFunc2@15>)"
printfn "%A" <@ fun x y -> x + y @> // generates usable expression tree
Quotations represent the F# code that was quoted syntactically. This means that if you write something like
<@ x @>
, the quotation will contain justValue
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 asReflectedDefinition
and is referred to by name in a quotation (e.g.<@ add @>
but not for examplelet 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: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):