TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Y combinator in Scheme

68 pointsby momo-reinaover 10 years ago

5 comments

jarcaneover 10 years ago
I like this explanation, because it focuses in it&#x27;s latter portion on the one thing that actually made Y click for me: expanding it.<p>I think it&#x27;s why it&#x27;s so short: the Y-combinator makes perfect sense if you explain it in the context of expansion rather than recursion. The best demonstrator of how it combinators work isn&#x27;t a bunch of algebraic derivations and explanations relative to tail-recursion, it&#x27;s seeing how they expand to resolve the function given. For me, it was stepping through a factorial function in Racket.<p>In the end I wound up including it in the Heresy standard library.
评论 #8846544 未加载
评论 #8845543 未加载
klibertpover 10 years ago
I recently found this talk: <a href="http://www.confreaks.com/videos/1287-rubyconf2012-y-not-adventures-in-functional-programming" rel="nofollow">http:&#x2F;&#x2F;www.confreaks.com&#x2F;videos&#x2F;1287-rubyconf2012-y-not-adve...</a> which I think it&#x27;s a good introductory material: it not only derives Y, but starts with introducing all the tools needed for the derivation and explains rationale for using given tool at every step of derivation. Nice, however rather long.<p>Personally I found &quot;The Little Schemer&quot; explanation the first that made it click for me. Its unique style of making you do the exercises even if you don&#x27;t do them (it&#x27;s hard to explain, just go and read the book) gives you an impression that you really understand what is happening.
dionidiumover 10 years ago
There are some good summaries here, too:<p><a href="http://stackoverflow.com/questions/93526/what-is-a-y-combinator/6714066" rel="nofollow">http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;93526&#x2F;what-is-a-y-combina...</a><p>Full disclosure: I ended up answering there as well, but I won&#x27;t say which one is mine.
stevenspasboover 10 years ago
I really liked this article: <a href="http://mvanier.livejournal.com/2897.html" rel="nofollow">http:&#x2F;&#x2F;mvanier.livejournal.com&#x2F;2897.html</a><p>I have been working through SICP and I ended up taking a weekend break from it to really understand everything in the article.
pashover 10 years ago
To understand the theory of recursive functions you must understand fixed points, but I think there&#x27;s a simpler way to understand the magic of the Y combinator.<p>Here&#x27;s how it works. Say we have a recursive function like <i>map</i>:<p><pre><code> map f [] = [] -- We&#x27;ll ignore the base case since there&#x27;s no recursion here map f (x:xs) = f x : map f xs -- This is the interesting part </code></pre> We want to write this more primitively, without explicit recursion. How can we do that? Well, if it&#x27;s possible at all, we obviously need to get rid of the <i>map</i> on the right hand side of the second case.<p>How? Well, let&#x27;s abstract over the recursive call, replacing it with a function that we&#x27;ll add as parameter to our definition:<p><pre><code> map&#x27; _ f [] = [] -- Still boring map&#x27; g f (x:xs) = f x : g g f xs -- Pay attention for later! </code></pre> (Read <i>map&#x27;</i> as &quot;map-prime&quot;, i.e., a variant of the definition of <i>map</i>.)<p>All we&#x27;ve done so far is replaced <i>map&#x27;</i> where it should be on the right-hand side of its own definition with <i>g</i>, and then added <i>g</i> as parameter of the function. We end up with a double <i>g</i> on the right-hand side because of that added parameter.<p>OK, now what? Well, we need somehow to make <i>g</i> be <i>map&#x27;</i>, the thing we&#x27;re defining. which means we need somehow to pass our definition of <i>map&#x27;</i> to itself, so that (in the second case) we&#x27;d end up with something that evaluates to:<p><pre><code> map&#x27; map&#x27; f (x:xs) = f x : map&#x27; map&#x27; f xs </code></pre> Then the right hand side would obviously be right; it&#x27;s what we were shooting for at the start (assuming we can get <i>map&#x27; map&#x27;</i> to equal <i>map</i>, which is what we&#x27;re trying to do). The left hand side looks a little strange [0], but it&#x27;s just saying that we need the first parameter of our definition to be the the thing we&#x27;re defining.<p>So how do we make this happen? Well, what is <i>map map f (x:xs)</i>? It&#x27;s <i>map</i> applied to itself, then to some other arguments we need. So the key, it seems, is to figure out how to apply <i>map</i> to itself. Well, in the lambda calculus that&#x27;s pretty easy [1]:<p><pre><code> why f x y = f f x y </code></pre> That is, <i>why</i> is just<p><pre><code> lambda f. lambda x. lambda y. (f f) x) y </code></pre> OK, so <i>fix</i> takes a function and applies it to itself (after applying it first to arguments <i>x</i> and <i>y</i>). Great. That&#x27;s what we needed. Now we can take our defintion of <i>map&#x27;</i> (the one marked <i>Pay attention for later!</i> above) and do this:<p><pre><code> map = why map&#x27; </code></pre> And I&#x27;ve re-used the name <i>map</i> there because we can easily show that this definition is equivalent to our original definition of <i>map</i> by showing that it reduces to the same expression:<p><pre><code> map f (x:xs) = why map&#x27; f (x:xs) == (by def. of `why`) map&#x27; map&#x27; f (x:xs) == (by def. of `map&#x27;` f x : map&#x27; map&#x27; f xs </code></pre> Which, if you keep expanding the expression <i>map&#x27; map&#x27; f xs</i>, you will see is indeed equal to the definition of <i>map</i>.<p>Voilà. So that wasn&#x27;t too hard. It&#x27;s basically two steps: (1) abstract over the recursive call, then (2) figure out how to pass the function you&#x27;re defining to itself. If you look at the Y combinator, you&#x27;ll see that that&#x27;s exactly what&#x27;s going on there.<p>If this didn&#x27;t make a lot of sense to you, it&#x27;s probably because I wrote it on my iPad at 4:30 in the morning. It really is just those two steps: abstract over the recursive call, then self-apply. ...<p>To get deeper into the recursive mindset (if you&#x27;re not there yet) and to build up deliberately to the Y combinator, take a look at one of my favorite books on functional programming, <i>The Little Schemer</i> [2]. (And watch out for the jelly stains!)<p>------<p>0. And it&#x27;s ill typed, but never mind that. It&#x27;s not possible to define the Y combinator (or any other fixed-point combinator) in the simply typed-lambda calculus, so just imagine that my Haskell-style syntax is untyped, like the basic lambda calculus.<p>1. Although, again, there&#x27;s no way to give <i>fix</i> a good type in the simply typed lambda calculus.<p>2. <a href="http://www.amazon.com/The-Little-Schemer-4th-Edition/dp/0262560992" rel="nofollow">http:&#x2F;&#x2F;www.amazon.com&#x2F;The-Little-Schemer-4th-Edition&#x2F;dp&#x2F;0262...</a>
评论 #8844136 未加载
评论 #8844470 未加载
评论 #8843964 未加载