SORU
4 Ocak 2010, PAZARTESİ


Nasıl y-kombinatorik olmadan tanımlamak&; rec""?

Neredeyse tüm örneklerde, y-kombinatorik ML-türü dilleri böyle yazılır:

let rec y f x = f (y f) x
let factorial = y (fun f -> function 0 -> 1 | n -> n * f(n - 1))

Bu beklendiği gibi çalışır, ama y-kombinatorik let rec ... kullanarak tanımlamak için hile yapmak gibi geliyor.

Özyineleme kullanmadan bu kombinatorik tanımlamak için, standart bir tanımı kullanmak istiyorum:

Y = λf·(λx·f (x x)) (λx·f (x x))

Doğru çeviri şu şekildedir:

let y = fun f -> (fun x -> f (x x)) (fun x -> f (x x));;

Ancak, F# türlerini anlamaya olamaz yakınıyor:

  let y = fun f -> (fun x -> f (x x)) (fun x -> f (x x));;
  --------------------------------^

C:\Users\Juliet\AppData\Local\Temp\stdin(6,33): error FS0001: Type mismatch. Expecting a
    'a    
but given a
    'a -> 'b    
The resulting type would be infinite when unifying ''a' and ''a -> 'b'

Nasıl F y-kombinatorik, yazmanın ne anlamı var# let rec ... kullanmadan?

CEVAP
4 Ocak 2010, PAZARTESİ


Derleyici, puan yok yazın atanabilir x böylece ifade (x x) iyi yazılmış (bu kesinlikle doğru değil; sen-ebilmek açıkça yazın x obj->_ - bakın benim son paragraf). Çok benzer bir ifade çalışması, özyinelemeli bir tür bildirerek bu sorunu geçici çalışabilirsiniz:

type 'a Rec = Rec of ('a Rec -> 'a)

Şimdi Y-kombinatorik olarak yazılabilir:

let y f =
  let f' (Rec x as rx) = f (x rx)
  f' (Rec f')

Ne yazık ki, bu F çünkü çok yararlı olmadığını göreceksiniz# sıkı bir dildir, yani bu kombinatorik kullanarak tanımlamak için deneyin herhangi bir işlevi bir yığın taşması neden olur. Bunun yerine, Y-kombinatorik (\f.(\x.f(\y.(x x)y))(\x.f(\y.(x x)y))) uygulamalı-sipariş sürümü kullanmanız gerekir:

let y f =
  let f' (Rec x as rx) = f (fun y -> x rx y)
  f' (Rec f')

Başka bir seçenek açık tembellik normal sipariş Y-kombinatorik: tanımlamak için kullanmak olacaktır

type 'a Rec = Rec of ('a Rec -> 'a Lazy)
let y f =
  let f' (Rec x as rx) = lazy f (x rx)
  (f' (Rec f')).Value

Bu özyinelemeli fonksiyon tanımları şimdi tembel değeri (Value özelliğini kullanarak) kesin bir güce ihtiyaç olduğunu düşünelim.

let factorial = y (fun f -> function | 0 -> 1 | n -> n * (f.Value (n - 1)))

Ancak, yapay bir dil gibi işlev olmayan özyinelemeli değerleri tanımlayabilirsiniz avantajı vardır:

let ones = y (fun ones -> LazyList.consf 1 (fun () -> ones.Value))

Son bir alternatif olarak, daha iyi boksu ve downcasting tarafından yazılmamış lambda calculus yaklaşık deneyebilirsiniz. Bu, (yine Y-kombinatorik bu uygulamalı-sipariş sürümü kullanarak) verir:

let y f =
  let f' (x:obj -> _) = f (fun y -> x x y)
  f' (fun x -> f' (x :?> _))

Bu Boks ve kutulama gereksiz neden olan en belirgin dezavantajı var, ama en azından bu tamamen uygulanması için iç ve gerçekte hiçbir zaman zamanında başarısızlığa götürür.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • fufko

    fufko

    27 ŞUBAT 2006
  • Garrett Müller

    Garrett Mül

    26 HAZİRAN 2009
  • Nick Pitera

    Nick Pitera

    8 NİSAN 2006