Внедрение определения переменной в цитату F # - PullRequest
0 голосов
/ 13 мая 2018

У меня есть собственное определение переменной, которое я хочу вставить в цитату. Возможно ли это даже с синтаксисом цитат сахар?

Что я хотел сделать:

open Microsoft.FSharp.Quotations
let var = Var("myvar", typeof<int>)
let op = <@@ fun l -> match l with
        | [] -> 0
        | %%myvar :: _ -> ... @@>

Я также пытался <@@ let %%myvar = ... @@> с той же целью.

В обоих случаях я получил FS0010 «Неожиданный префиксный оператор в привязке» или «... в сопоставлении с образцом».

Есть ли способ ввести существующий Var, как это? Или мне нужно прибегнуть к генерации всего выражения вручную?

PS: Я использую все это, чтобы перевести некоторые другие AST в цитату F #.

1 Ответ

0 голосов
/ 14 мая 2018

То, что вы описываете в своем вопросе, действительно бессмысленно. Вы не можете объединить 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), потому что приложение функции имеет более высокий приоритет, чем оператор %%.


Если я ошибаюсь в угадывании твоего намерения, уточни это, и я с удовольствием исправлю ответ.

...