don't inline image
[lambda.git] / rosetta1.mdwn
index 4e37427..1ae2460 100644 (file)
@@ -2,12 +2,14 @@
 
 ## Can you summarize the differences between your made-up language and Scheme, OCaml, and Haskell? ##
 
-The made-up language we wet our toes in in week 1 is called Kapulet. (I'll tell you the story behind its name sometime.) The purpose of starting with this language is that it represents something of a center of gravity between Scheme, OCaml, and Haskell, and also lacks many of their idiosyncratic warts. One downside is that it's not yet implemented in a form that you can run on your computers. So for now, if you want to try out your code on a real mechanical evaluator, you'll need to use one of the other languages.
+The made-up language we wet our toes in in week 1 is called Kapulet. (I'll tell you [the story behind its name](randj.jpg) sometime.) The purpose of starting with this language is that it represents something of a center of gravity between Scheme, OCaml, and Haskell, and also lacks many of their idiosyncratic warts. One downside is that it's not yet implemented in a form that you can run on your computers. So for now, if you want to try out your code on a real mechanical evaluator, you'll need to use one of the other languages.
 
 Also, if you want to read code written outside this seminar, or have others read your code, for these reasons too you'll need to make the shift over to one of the established languages.
 
 We hope, though, that learning Kapulet first puts you in a position to make that shift more effortlessly, and also to more quickly see the places where there's underlying unity to Scheme, OCaml, and Haskell, despite their diverse syntaxes. (And idiosyncratic warts.)
 
+This is a complex document. We don't expect that you will be learning all of these languages simultaneously. But you may find it helpful to read through the whole thing to get a broad overview, then consult it more carefully about the language you're focused on learning at any given point. You may also find it helpful to consult when confronting code you don't understand in one of the other languages. There are important parts of these languages that aren't covered here, especially parts concerning types and monads and continuations, that we will be discussing later in the seminar. We will add additional Rosetta pages for those later. If you master the ideas summarized here, however, you will have a good understanding of the basic skeleton of each of these languages.
+
 
 
 
@@ -149,7 +151,7 @@ OCaml and Haskell also permit defining functions in uncurried form:
 
     (* OCaml *)
     let add  = fun (x, y) -> x + y (* uncurried*) in
-    let add2 = fun add 2 in ...
+    let add2 = add 2 in ...
 
 Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
 
@@ -181,7 +183,7 @@ Whereas in Kapulet `( & )`, `(x & )`, and `( & xs)` are all sections using its s
 
 Third, as [[mentioned above|rosetta1#pre-curried]], OCaml's and Haskell's `( + )` and the like evaluate to *curried* functions.
 
-Fourth, in Kapulet, `( - 10)` expresses λ `x. x - 10` (consistently with `(10 - )`), but Haskell (and OCaml) treat this specific form differently, and interpret it as meaning the integer `- 10`. Here's how to express some things in Kapulet:
+Fourth, in Kapulet, `( - 10)` expresses λ `x. x - 10` (consistently with `(10 - )`), but Haskell (and OCaml) treat this specific form differently, and interpret it as meaning the integer `-10`. Here's how to express some things in Kapulet:
 
     # Kapulet
     (0 - 2)
@@ -198,7 +200,7 @@ and here are their translations into natural Haskell:
     negate        -- (0 - ) also works
     ( - ) 5 3
 
-OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml as either `3 * ( -2 )` or as `3 * ~-2`.
+OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml either like that, or as `3 * ( -2 )`, or as `3 * ~-2`.
 
 I know all these languages fairly well, and I still find this fourth issue difficult to keep track of. You may be starting to understand why I spoke of "warts."
 
@@ -260,8 +262,8 @@ Here are some list functions in Kapulet:
     (mem)        # infix syntax, 2 mem [1, 2, 3] == 'true
     nth          # nth [10, 20, 30] 1 == 20, because 10 occupies position 0
                  # fails if the index is out of bounds
-    all? p xs    # all? odd? [1, 3, 5] == 'true
-    any? p xs    # any? even? [1, 3, 5] == 'false
+    all p xs     # all odd? [1, 3, 5] == 'true
+    any p xs     # any even? [1, 3, 5] == 'false
 
 
 
@@ -343,7 +345,7 @@ elements at different stages in a program's evaluation
 
 Many Scheme implementations also provide immutable versions of `list`s and `vector`s, more closely approximating the sequences/lists in Kapulet, Haskell, and OCaml. With some configurations, Racket even makes the immutable versions the defaults. But none of these are yet part of the official Scheme standard. Also, difference 1 is present in all Scheme implementations. This makes Scheme's `list`s and `vector`s in some ways more akin to *tuples* in the other languages (to "proper" tuples in Kapulet) (see [[below|rosetta1#tuples]]).
 
-(OCaml does have `Array` values, and Haskell has `Data.Array.MArray` values, both of which are similar to Scheme's mutable `vector`s. But they are more difficult to use.)
+(OCaml does have `Array` values, and Haskell has `Data.Array.MArray` values, both of which are similar to Scheme's mutable `vector`s, at least in respect 2. But they are more difficult to use.)
 
 <a id=writing-scheme-lists></a>
 There are also some differences in how `list`s are specified in Scheme versus the other languages. In Scheme, one writes the empty list like this:
@@ -393,7 +395,7 @@ Here are the `list` functions in Scheme corresponding to the functions listed in
 <!-- memv, member return the first tail headed by the matching element, or #f -->
 
 All of the functions listed as missing from the official Scheme standard can be found in various add-on libraries, or you could define them yourself if you had to.
-
+<!-- TODO Scheme extra list functions -->
 
 
 
@@ -436,13 +438,13 @@ This is not the same as the truth-value, nor is it the same as the atomic symbol
 
 ### Other functions
 
-These functions are roughly the same in Kapulet, OCaml, and Haskell: `succ`, `pred`, `fst`, `snd`. The official Scheme standard doesn't include any `succ` or `pred` functions, but Racket and Chicken both have `add1` and `sub1`. Depending on what Scheme values you take to correspond to tuples in the other languages, `fst` and `snd` may correspond to `car` and `cdr`. (These also correspond to `head` and `tail` when applied to lists.)
+These functions are roughly the same in Kapulet, OCaml, and Haskell: `succ`, `pred`, `fst`, `snd`. The official Scheme standard doesn't include any `succ` or `pred` functions, but Racket and Chicken both have `add1` and `sub1`. Depending on what Scheme values you take to correspond to tuples in the other languages, `fst` and `snd` may correspond to Scheme's `car` and `cdr`. (These also correspond to `head` and `tail` when applied to lists.)
 
-Kapulet's `(comp)`, `odd?`, `even?`, and `swap` (defined in homework) are Haskell's `( . )`, `odd`, `even`, and `Data.Tuple.swap`. None of these are predefined in OCaml.
+Kapulet's `(comp)`, `odd?`, `even?`, and `swap` are Haskell's `( . )`, `odd`, `even`, and `Data.Tuple.swap`. None of these are predefined in OCaml.
 
 Kapulet's `dup` isn't predefined in Haskell but can be easily expressed as `\x -> (x, x)`.
 
-These are the same in Kapulet and Haskell (modulo the differences between [[Kapulet's multivalues|topics/week1#lightweight]] or "lightweight tuples" and Haskell's tuples), aren't predefined in OCaml: `id`, `const`, `flip`, `curry`, `uncurry`. None of these are predefined in OCaml.
+These are the same in Kapulet and Haskell (modulo the differences between [[Kapulet's multivalues|topics/week1#lightweight]] or "lightweight tuples" and Haskell's tuples): `id`, `const`, `flip`, `curry`, `uncurry`. None of these are predefined in OCaml.
 
 Kapulet and Haskell both have `( $ )`, which was explained [[in the course notes|topics/week1_advanced_notes#dollar]]. OCaml expresses this as `( @@ )`. (OCaml also uses `|>` to express the converse operation: `f x`, `f @@ x` and `x |> f` all mean the same.)
 
@@ -777,9 +779,9 @@ does. There's a similar form for `letrec`.
 OCaml can do the same:
 
     let
-      x = 0;;
+      x = 0 ;;
     let
-      x = 1;;
+      x = 1 ;;
     x
 
 The double-semicolons are hints to OCaml's "toplevel interpreter" that a syntactic unit has finished. In some contexts they're not needed, but it does no harm to include them if you're not sure.
@@ -821,7 +823,7 @@ Note there are no semicolons here. These are called "toplevel declarations" of t
 
 defines `f` as a function that returns the length of a single List argument. (You can also do that *inside* Haskell's `let` constructions, too.) This is what corresponds *in Haskell files* to `let ... end` in Kapulet.
 
-Haskell also permits multiple declarations of this sort inside its `let` and `where` constructs, too. Moreover, there declarations can also have [[pattern guards|rosetta1#haskell-guards]], as in:
+Haskell also permits multiple declarations of this sort inside its `let` and `where` constructs, too. Moreover, these declarations can also have [[pattern guards|rosetta1#haskell-guards]], as in:
 
     -- Haskell file.fs
     f [] = 0