robkuz
robkuz

Reputation: 9934

checking Code Quotation structure during compile time

can I define a quotation expression paramter such that not only the resulting type of the expression is compile time checked but also the call site expression.

lets see an example:

type A = {
    a : int
}

type Checker () =
     static member Check(e : Expr<int>) : ResultType = ...

The following obviously type check

let a = { a = 1 }
Checker.Check <@ a.a @>

Resulting in an actual Expression similar to PropertyGet( ..., PropertyGet (....), a).

And now some other way

let getInt (a:A) : int = a.a

The following also compiles

Checker.Check <@ getInt a @>

However how can I prevent that second example compiles and only allow for PropertyGets? (just as an example).
I know I can check the structure of the expression at run time - but I like to have an compile time check.

Upvotes: 2

Views: 101

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243071

As Fyodor said in a comment, there is no way to ensure that quotations are only of a certain shape at compile-time. This is quite unfortunate, but all quotation-based (or expression-tree based) libraries suffer from this (most notably LINQ) and if your requirement is "only property-getters" then I suppose you can probably just leave this as a runtime check.

If I really wanted to guarantee this, I would probably try to use the F# Compiler Service, which lets you get typed expression tree. You could then walk over the tree and find all quotations in the project and report the errors (it could be done in some extensible way as a linter plugin, which others might benefit from too).

If you went in the DSL direction, then you could write, say, a |> get "foo" |> get "bar" (using pipe), or a?foo?bar (using the ? operator), but then you lose checking on the names, which seems to be worse than not being able to check the correct shape of a quotation.

Upvotes: 1

Related Questions