То, что вы описываете в своем вопросе, действительно бессмысленно. Вы не можете объединить Var
в выражение. Только значение типа Expr
может быть сращено. Если вы создали экземпляр Expr
наших из var
с помощью конструктора Expr.Var
, тогда будет возможно соединение:
let var = Expr.Var( Var("myvar", typeof<int>) )
let op = <@@ fun l -> %%var @@>
Но это не позволит вам сделать то, что вы пытаетесь сделать: вы не можете склеить выражение в позиции шаблона (левая сторона стрелки ->
внутри match
- это то, что мы называем «шаблон», и так же левая сторона знака равенства =
внутри let
). Вы можете объединять только выражения, а не другие части синтаксиса. Цитаты кода F # не так бесплатны, как макросы Lisp или TemplateHaskell.
Правда, не совсем понятно, что вы на самом деле пытаетесь сделать.
Одна возможность вашего истинного намерения, которая приходит на ум, заключается в следующем: вы хотите сопоставить эту переменную в левой части стрелки ->
, а затем передать ее какой-то другой функции, которая создаст правую часть стрелки ->
. Примерно так:
let mkRightSide var = <@@ %%var + 42 @@>
let var = Expr.Var( Var("myvar", typeof<int>) )
let op = <@@ fun l -> match l with
| [] -> 0
| %%var :: _ -> %%(mkRightSide var) // Doesn't compile
@@>
Что даст следующую цитату:
fun l -> match l with
| [] -> 0
| myvar :: _ -> myvar + 42
Если это ваше намерение, тогда я предлагаю, чтобы mkRightSide
возвратил функцию, которая просто взяла бы myvar
в качестве параметра:
let mkRightSide = <@@ fun myvar -> myvar + 42 @@>
let op = <@@ fun l -> match l with
| [] -> 0
| (myvar:int) :: _ -> (%%mkRightSide) myvar @@>
Выше приведено следующее предложение:
fun l -> match l with
| [] -> 0
| myvar :: _ -> (fun myvar -> myvar + 42) myvar
Примечание 1: аннотация типа на myvar
необходима, потому что ваши цитаты нетипизированы. Поскольку mkRigthSide
не содержит никакой информации о типе, компилятор не может вывести myvar
как int
и вместо этого делает его универсальным, что вызывает несоответствие типов при попытке объединения.
Примечание 2: скобки вокруг (%%mkRightSide)
обязательны. Без них компилятор понял бы это как %%(mkRightSide myvar)
, потому что приложение функции имеет более высокий приоритет, чем оператор %%
.
Если я ошибаюсь в угадывании твоего намерения, уточни это, и я с удовольствием исправлю ответ.