![]() ![]() (in particular the “001-infinitary” one), where $y \rightarrow_\beta^\infty \lambda f.fff\ldots$, see for instance the original paper, the survey in Barendregt and Manzonetto's Satellite, or some recent presentations here or there. This can be turned into a “real” common reduct in an infinitary λ-calculus Recall the head-internal decomposition of β-reduction: a reduction $M \rightarrow_(\theta) = \lambda f.fff\ldots$ The clue here is that this effectively stops the computation at each step until it's actually put into use.The result, left as an exercise by Barendregt (Exercise 6.8.9), is proved by Klop in a 2007 paper (Proposition 1.2). In the same manner (lambda args (apply (g g) args)) is the same as (g g) and you can see that by just applying substitution rules. If you have a function add1 you can make a wrapper (lambda (x) (add1 x)) that you can use instead and it will work. We know (g g) becomes a function so we just give f a function that when applied will generate the actual function and apply it. To salvage that we don't apply (g g) right away. Reduction 4.1 Other notions of reduction 4.2 Reduction strategies 5. If you look at how this would be applied with an argument you'll notice that Y never returns since before it can apply f in (f (g g)) it needs to evaluate (g g) which in turn evaluates (f (g g)) etc. ![]() Well the normal order version looks like this: (define Y Id especially appreciate an explanation alongside any code. I would like to understand how to build this function out, and incorporate recursion with the Y combinator. So you are asking how the evaluation gets delayed. Im very inexperienced with Racket, and the Lambda Calculus is quite a head scratcher as someone whos never picked it up until recently. Notice the implementations is exactly the same and the difference is how the reference to itself is handled. Unfortunately many Prolog systems allow a solution for A A -> B. Since self application is part of Y combinator, its also not possible to give a type to it. If it where possible then t would have a type A -> B, and we would have A A -> B. ![]() (else (ackermann (- m 1) (ackermann m (- n 1)))))))) Typing should disallow self application, it should not be possible to find a type for (t t). This can be done with Z like this: ((Z (lambda (ackermann) Imagine the Ackermann function: (define ackermann The book Types and Programming Languages (briefly, TAPL) is a popular introduction to type systems and programming language theory. Notice this version uses apply to support multiple argument functions. It's just a little more code that does exactly the same. Now the first thing that happens when this is applied is (g g) and since you can always substitute a whole application with the expansion of it's body the body of the function can get rewritten to: (define Z The applicative version of Y is often called a Z combinator: (define Z Typing the Z-combinator requires either to allow recursive types (with the -rectypes option) or to box the type recursion inside a type constructor: type a fix Fix of a fix -> a) let z f (fun (Fix x as fx) -> f (fun v -> x fx v)) (Fix (fun (Fix x as fx) -> f (fun v -> x fx v))) which requires x to accept itself as an argument. In a lazy language like Lazy Racket you can use the normal order version, but not in any of the applicative order programming languages like Scheme. ![]()
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |