Reputation: 9934
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 PropertyGet
s? (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
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