Permalink
Browse files

publish

  • Loading branch information...
1 parent 503ee01 commit 5b67fa1ead7b0a9c29f855d971551c549dbf35a5 @twopoint718 committed Sep 4, 2012
Showing with 197 additions and 2 deletions.
  1. +197 −2 blog.rss
View
199 blog.rss
@@ -4,8 +4,203 @@
<title>sencjw.com - rss feed</title>
<description>recent blog posts from sencjw.com</description>
<link>http://sencjw.com/blog.html</link>
-<lastBuildDate>Sat, 05 May 2012 18:56:54 +0000</lastBuildDate>
-<pubDate>Sat, 05 May 2012 18:56:54 +0000</pubDate>
+<lastBuildDate>Tue, 04 Sep 2012 12:31:28 +0000</lastBuildDate>
+<pubDate>Tue, 04 Sep 2012 12:31:28 +0000</pubDate>
+<item>
+ <title><![CDATA[the dipert problem]]></title>
+ <description><![CDATA[
+Recently, [Alan Dipert](http://alan.dipert.org/) dropped a bomb on the
+twittersphere with his posing of [this question](https://twitter.com/alandipert/status/241575872937750529) (warning there are spoilers in the replies):
+
+"pop quiz: solve <http://www.4clojure.com/problem/107> point-free.
+answer must be a function value! #clojure"
+
+In case your office has banned 4clojure for being a huge distraction,
+I'll post the problem here:
+
+ (= 256 ((__ 2) 16),
+ ((__ 8) 2))
+
+ (= [1 8 27 64] (map (__ 3) [1 2 3 4]))
+
+ (= [1 2 4 8 16] (map #((__ %) 2) [0 1 2 3 4]))
+
+In problem 107, your challenge is to write a function that satisfies
+all of these (it could be dropped in place of the `__`s above). I will
+let you go take a crack at solving it. Because up next is some serious
+spoiler action.
+
+Got your solution? I came up with this:
+
+ (fn [x] (fn [y] (reduce * (repeat x y))))
+
+or (what I was really doing) in Haskell:
+
+ f :: Int -> Int -> Int
+ f x y = foldl1 (*) (replicate x y)
+
+We are doing manual exponentiation: "make a list of *y*s that is *x* in
+length (e.g. `replicate 8 2 == [2, 2, 2, 2, 2, 2, 2, 2]`). Then you
+just run multiplication through the list:
+
+ foldl1 (*) [2,2,2,2,2,2,2,2] == 2 * 2 * 2 * ... 2 == 256
+
+Now comes the "Dipert Problem." He has told us that we have to rewrite
+the solution (or any solution) using so-called *point-free* style. I'm
+sure that there's more to it, but essentially that means that *we are
+not allowed to mention any variables!* When I first heard about this
+style, it sounded impossible! The cool thing is that it *isn't* and it
+leads to some massively simple code. Let's try it out.
+
+I'm going to start with my solution above called `f` and then write
+some successive versions of it, each time, I'll remove a variable and
+call it the "next" version: `f1`, `f2`, okay? Cool.
+
+ f, f1, f2 :: Int -> Int -> Int
+ f x y = foldl1 (*) (replicate x y)
+
+For the first transformation, we need to get rid of the `y` that's
+hanging off the end of both sides of our equation. We'll need to juggle
+the innards a bit because here is what the types look like so far:
+
+ foldl1 (*) :: [Int] -> Int
+ replicate x y :: Int -> a -> [a]
+
+`replicate` takes two arguments and then produces a list that the
+`foldl1 (*)` wants to consume. The trouble is, and what tripped me up a
+bunch, is that I can't just do this:
+
+ foldl1 (*) . replicate
+
+Wah, wah (sad trombone). GHCI tells me:
+
+ Expected type: Int -> [c0]
+ Actual type: Int -> a0 -> [a0]
+
+Okay, that makes sense, for the fold and replicate to "line up" for
+composition, replicate has to take one argument then produce a list.
+The crux is that composition (the "dot" or period in the code) only
+works for single-argument-functons:
+
+ (.) :: (b -> c) -> (a -> b) -> a -> c
+
+This is a little pipeline, but reversed because that's how mathematics
+does it. It says "the right-side function takes an *a* and gives a *b*,
+and the left-side function expects a *b* and gives a *c*; now you can
+stitch them together and have a function that *skips* the *b* and
+takes you right from *a* to *c*." But we have a function that looks like:
+
+ (a -> b -> c)
+
+on the right-hand side; it won't work. how do we convert a `(a -> b ->
+c)` to a `(a -> (b -> c))`? This way:
+
+ {-
+ f x y = foldl1 (*) ((replicate x) y)
+ f x y = (foldl1 (*) . (replicate x)) y
+ -}
+ f1 x = foldl1 (*) . (replicate x)
+
+*Note:* the first two lines are commented in case you are cut-n-pasting
+along. The first line just puts parenthesis in where they really are in
+haskell. Each time you see a function of two arguments, it *is really*
+a function which takes one argument and returns a function that expects
+the second argument! This weird but remarkable fact of haskell is
+called [currying](http://www.haskell.org/haskellwiki/Currying).
+
+Now, on to the second line, we see that we have the right types! (I am
+cheating a bit on types, if you like, you can define `rep` which *just*
+uses `Int`s)
+
+ replicate x :: Int -> [Int] -- cheating: where 'x' is a specific int
+ foldl1 (*) :: [Int] -> Int
+
+ foldl1 (*) . replicate x :: Int -> Int
+
+And that brings us to `f1`! We used grouping and composition to move
+the `y` outside the computation and then we dropped it from both sides.
+
+Next we'll tackle the x:
+
+ {-
+ f x = (foldl1 (*) .) (replicate x)
+ f x = ((foldl1 (*) .) . replicate) x
+ -}
+ f2 = (foldl1 (*) .) . replicate
+
+It may look different, but the same thing is going on. We can group the
+composition with the fold without changing anything. This is just like
+doing:
+
+ 3 + 4 == (3 +) 4
+
+Next we do that same trick again where we can now compose the inner
+functions because the types line up (again, I'm simplifying types a
+bit):
+
+ ((foldl1 (*) .) .) :: (a -> b -> [c]) -> a -> b -> c
+
+it looks a bit hairy, but in our case, it is just what we want! If I
+fill in the actual types we'll be using, it becomes clearer:
+
+ ((foldl1 (*) .) .) :: (Int -> Int -> [Int]) -> Int -> Int -> Int
+
+Booyah! This contraption takes a *function* of two `Ints` that produces
+a list of ints, `[Int]`. Well, that's just what `replicate` is! So if
+we then feed in replicate:
+
+ (foldl1 (*) .) . replicate :: Int -> Int -> Int
+
+And that's it, we have a point-free function that takes two `Int`s and
+returns an `Int`. And so that's our last, and final function:
+
+ f2 = (foldl1 (*) .) . replicate
+
+In general, and I don't know a term for this, but the operation of
+successive function composition lets us compose higher and higher arity
+functions together. Here's a dumb example using my little point-free `succ`
+function:
+
+ g :: Int -> Int
+ g = (+1)
+ (g .) :: (a -> Int) -> a -> Int
+ (g .) .) :: (a -> b -> Int) -> a -> b -> Int
+ (g .) .) .) :: (a -> b -> c -> Int) -> a -> b -> c -> Int
+
+Clear pattern. I kinda think of this as saying something like "please
+give me a function which *eventually* promises to give me what I want."
+The *eventually* part is essentially "after you've collected all the
+stuff you need." It would be trivially satisfied by some function that
+ignores its args and returns a constant:
+
+ (((g .) .) .) (\x y z -> 1) 4 5 6 == 2
+
+Remembering that `g` just increments, the x y z are *totally ignored*.
+The function supplied to the multiply-composed `g` is like some kind of
+integer "pre-processor"; the *x*, *y* and *z* can be whatever you need
+to do to figure out how to give g an integer. Or at least that's how
+I'm thinking of it.
+
+I had a lot of fun trying to figure this out!
+]]></description>
+ <link>blog.html#2012-09-03</link>
+ <guid>1445c3b04654edf2a94a8501c8313a22c513d0f9</guid>
+ <pubDate>Mon, 03 Sep 2012 00:00:00 +0000</pubDate>
+</item>
+<item>
+ <title><![CDATA[my "transparent web" talk]]></title>
+ <description><![CDATA[<iframe src="http://www.slideshare.net/slideshow/embed_code/14023703" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/twopoint718/the-transparent-web-14023703" title="The Transparent Web: Bridging the Chasm in Web Development" target="_blank">The Transparent Web: Bridging the Chasm in Web Development</a> </strong> from <strong><a href="http://www.slideshare.net/twopoint718" target="_blank">twopoint718</a></strong> </div>
+
+Without much ado at all, here's my talk. I'm covering the *real*
+basics of using both [Ur/Web](http://www.impredicative.com/ur/)
+and [Opa](http://opalang.org/). I create a basic "Hello world"
+page in each and then I go on to write a little "comments"
+system.
+]]></description>
+ <link>blog.html#2012-08-22</link>
+ <guid>b42bab6db5d8328b7e335df29236c08c97fef9d6</guid>
+ <pubDate>Wed, 22 Aug 2012 00:00:00 +0000</pubDate>
+</item>
<item>
<title><![CDATA[my gpl talk]]></title>
<description><![CDATA[

0 comments on commit 5b67fa1

Please sign in to comment.