2017-01-26 32 views
6

ı tipindeki bu Fiyatlandırmamızı var diyelim Quotations.Expr<(int -> int -> int)>Kısmi uygulamalar

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

Ben reduce 1 expr olarak adlandırılan zaman esasen

<@ fun y -> 1 + y @> 

yani İstiyorum sağlaması hususundaki bir işlevi fun reduce x expr oluşturmak istiyorum Başka bir teklif üretmek için kısmen bir fiyat teklifi uygulamak.

Eminim ki bu yapılabilir, kimsenin bir fikri yok mu? Bu daha önce denendi mi? Hiçbir şey bulamıyor gibi görünüyor.

Ayrıca LISP'ye pek aşina değilim - ama bu aslında LISP makroları ile elde ettiğim şeye benziyor mu?

GÜNCELLEME: Teklifi azaltırken, ortaya çıkan ifade ağacında değerlendirilebilecek parçaları değerlendirmek istiyorum.

Örneğin: reduce true <@ fun b x y -> if b then x + y else x - [email protected]>, <@ fun x y -> x + y @> ile sonuçlanmalıdır.

+0

, ben Başka bir soru sormanızı öneririz. SO, küçük, kendi kendine yeten sorular ve cevaplar için gerçekten parlar. – CaringDev

+0

Understood @CaringDev – tejas

cevap

4

Eğer tırnak formunda fun x ... ait olduğunu biliyoruz, o zaman kolay:

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 @> 

Eğer ek ifadeleri basitleştirmek istiyorsanız, o zaman cevap vermek gerekir bazı hafif zor sorular vardır:

  • Yan etkilerden mi bahsediyorsunuz? <@ fun x y -> printfn "%i" x @> ile başlayıp x için 1 ile değiştirirseniz, <@ fun y -> printfn "%i" 1 @>'un basitleştirilmiş sürümü nedir? Bu, her çağrıldığında 1'u yazdırmalıdır, ancak hangi ifadelerin yan etkilere neden olabileceğini bilmedikçe, hiçbir şeyi basitleştiremezsiniz. Bunu görmezden gelirseniz (hiçbir ifade yan etkilere neden olmazsa), doğruluk maliyetlerinde işler çok daha basit hale gelir.
  • Basitleştirme ne anlama geliyor? Değiştirmeden sonra <@ fun y -> y + 1 @> aldığımı varsayalım. Öyleyse, let f y = y+1 in <@ f @> eşdeğerini basitleştirmek için iyi mi yoksa kötü mü? Bu kesinlikle "daha basittir", sadece bir değer içeren önemsiz bir ifadedir, ancak değer artık opak bir işlevdir. <@ fun y -> 1 + (fun z -> z) y @>'um varsa ne olur? İçsel işlevi bir değere ya da kötüye basitleştirmek tamam mı? Yan etkileri göz ardı edebilirsiniz ve biz hiç bir değeri olan bir işlev yerine istemiyorsanız

, o zaman böyle bir sadeleştirme fonksiyonu tanımlayabiliriz:

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 

Not bu hala olmayabilir İstediğiniz kadar şeyi basitleştirin; örneğin <@ (fun x -> x) 1 @>, <@ (fun x (y:int) -> x) 1 @> gibi basitleştirilmeyecektir.

+0

Bu, değerlendirilebilecek parçaları doğru değerlendiremez mi? Örneğin, 'eğlenceli bxy -> b ise x + y else x -y ' ' Alt doğru xy expr 'çağrıldığında," xy -> x + y "eğlence ile sonuçlanmalıdır. – tejas

+0

@tejas - düzenleme başlığına bakın – kvb

+0

Teşekkürler Kvb, bana devam edecek kadar verdin. – tejas

2

Ekleme tırnak alıntılar gömme bir yoludur:

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

reduce tip vardır 'a -> Expr<('a -> 'b)> -> Expr<'b>

Kullanımı: @kvb cevap basitleştirilmesi ifadeler için yararlı ipuçları sağlar

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

Ekleme bilmeniz gereken iyi bir şeydir, ama soruyu yanıtlamadığını düşünmüyorum (düzenleme işleminden önce bile) - '1 q'yu azaltma <@ (xy -> x + y) eşdeğerdir 1 @> ', <@ fun y -> 1 + y @ '' istenildiği gibi. Bunlar semantik olarak eşdeğer olsa da, alıntılar ile uğraşırken sözdizimsel yapıyı da sık sık önemser. – kvb

+0

@kvb Kesinlikle! Bu sadece daha geniş bir görünüm sunmalı ve IMO "Kısmi uygulama ..." ve "... aslında ..." ile uyumludur. Bu soruya karşı çıkmış bir başkası hala cevabımı faydalı bulabilir, bu yüzden şimdilik buradan ayrılacağım. – CaringDev