2017-01-26 6 views
6

Скажем, у меня есть эта цитата типа Quotations.Expr<(int -> int -> int)>Частичное применение F # Котировки

<@ fun x y -> x + y @> 

Я хочу создать функцию fun reduce x expr, что при вызове в качестве reduce 1 expr бы существенно уступать

<@ fun y -> 1 + y @> 

т.е. я хочу частично примените цитату, чтобы произвести другую цитату.

Я уверен, что это выполнимо, есть ли у кого-нибудь мысли? Проводилось ли это раньше? Кажется, ничего не может найти.

Также я не очень хорошо знаком с LISP - но по существу ли это похоже на то, что я могу достичь с помощью макросов LISP?

UPDATE: Уменьшая предложение, я хотел бы оценить детали, которые могут быть оценены в полученном дереве выражений.

Например: reduce true <@ fun b x y -> if b then x + y else x - [email protected]> должно содержать <@ fun x y -> x + y @>.

+0

Хотя @kvb ответ дает полезные советы для упрощения выражений, я рекомендуем задать другой конкретный вопрос. SO действительно сияет для маленьких, автономных вопросов и ответов. – CaringDev

+0

Understood @CaringDev – tejas

ответ

4

Если вы знаете, что ваша цитата из формы fun x ..., то это легко:

let subst (v:'a) (Patterns.Lambda(x,b) : Expr<'a->'b>) = 
    b.Substitute(fun x' -> if x = x' then Some (Expr.Value v) else None) 
    |> Expr.Cast<'b> 

subst 1 <@ fun x y -> x + y @> 

Если вы дополнительно хотите упростить выражения, то есть немного каверзные вопросы, которые вы должны будете ответить:

  • Вас интересуют побочные эффекты? Если я начну с <@ fun x y -> printfn "%i" x @>, и я заменю на 1 на x, то какая у упрощенная версия <@ fun y -> printfn "%i" 1 @>? Это должно печатать 1 каждый раз, когда он вызывается, но если вы заранее не знаете, какие выражения могут вызывать побочные эффекты, вы почти никогда ничего не сможете упростить. Если вы проигнорируете это (если никакое выражение не вызывает побочные эффекты), то вещи становятся намного проще за счет верности.
  • Что означает упрощение? Предположим, я получил <@ fun y -> y + 1 @> после замены. Тогда хорошо или плохо, чтобы упростить это до эквивалента let f y = y+1 in <@ f @>? Это определенно «проще» в том, что это тривиальное выражение, содержащее только значение, но значение теперь является непрозрачной функцией. Что делать, если у меня есть <@ fun y -> 1 + (fun z -> z) y @>? Можно ли упростить внутреннюю функцию до значения или плохо?

Если мы можем игнорировать побочные эффекты, и мы никогда не хотим, чтобы заменить функцию со значением, то вы могли бы определить функцию упрощения, как это:

let reduce (e:Expr<'a>) : Expr<'a> = 
    let rec helper : Expr -> Expr = function 
    | e when e.GetFreeVars() |> Seq.isEmpty && not (Reflection.FSharpType.IsFunction e.Type) -> // no free variables, and won't produce a function value 
     Expr.Value(Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation e, e.Type) 
    | ExprShape.ShapeLambda(v, e) -> Expr.Lambda(v, helper e) // simplify body 
    | ExprShape.ShapeCombination(o, es) -> // simplify each subexpression 
     ExprShape.RebuildShapeCombination(o, es |> List.map helper) 
    | ExprShape.ShapeVar v -> Expr.Var v 

    helper e |> Expr.Cast 

Обратите внимание, что это по-прежнему не может упрощайте то, что вам нужно; например, <@ (fun x (y:int) -> x) 1 @> не будет упрощен, хотя <@ (fun x -> x) 1 @> будет.

+0

Это не будет оценивать детали, которые можно оценить правильно? Например, 'fun bxy -> if b then x + y else x -y' При вызове' subst true xy expr' должно получиться 'fun xy -> x + y' – tejas

+0

@tejas - см. Мое редактирование – kvb

+0

Спасибо @kvb, вы дали мне достаточно, чтобы продолжить. – tejas

2

Сращивание является удобным способом вложения цитаты в цитатах:

let reduce x expr = 
    <@ (%expr) x @> 

reduce имеет тип 'a -> Expr<('a -> 'b)> -> Expr<'b>

Использование:

let q = <@ fun x y -> x + y @> 
let r = reduce 1 q // Expr<int -> int> 
let s = reduce 2 <| reduce 3 q // Expr<int> 
let t = reduce "world" <@ sprintf "Hello %s" @> // Expr<string> 
+0

Склеивание - это хорошая вещь, о которой нужно знать, но я не думаю, что она отвечает на вопрос (даже до редактирования) - 'уменьшение 1 q' приводит к эквиваленту' <@ (fun xy -> x + y) 1 @> ', а не' <@ fun y -> 1 + y @> 'по желанию. Хотя они семантически эквивалентны, при работе с котировками часто также заботятся о синтаксической структуре. – kvb

+0

@kvb Абсолютно! Это должно обеспечить более широкий обзор, и ИМО подходит для «частичного применения ...» и «... по существу ...». Кто-то другой, спотыкающийся по этому вопросу, может все же найти мой ответ полезным, поэтому я оставлю его здесь в настоящее время. – CaringDev

Смежные вопросы