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
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.
Nasıl "yinelenen OLMADAN birden f...
İki alanları tanımlamak için nasıl &qu...
Tanımlamak için nasıl "türü bir ç...
Nasıl kullanılır "&; raylar üzeri...
Herhangi bir veri kaybı olmadan bir ta...