X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=rosetta1.mdwn;h=0a09c7c9f7771fed33da50c62f5371fb8e578d84;hp=1ae2460764444a8d6ae293218385c6bd2e94e495;hb=020566910974049e4cd9cbc9279a781768e1817c;hpb=73468d0b4529a8dc0fd0ac47f4b2fdc4af94c3ec
diff --git a/rosetta1.mdwn b/rosetta1.mdwn
index 1ae24607..0a09c7c9 100644
--- a/rosetta1.mdwn
+++ b/rosetta1.mdwn
@@ -2,7 +2,7 @@
## 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](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.
+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.
@@ -44,7 +44,7 @@ These block comments also nest. Another form of block comments is `#;( ... )`. T
### Variables
-Our [[syntax for variables|topics/week1#variables]] in Kapulet is close to that in the other languages. Haskell and OCaml differ only in that they do not permit trailing `?` or `!`; however, they do permit trailing `'`s (and even permit `'`s *in the middle* of a variable too, which Kapulet does not). Scheme permits all of these characters, plus many more punctuation symbols as well, to occur anywhere in a variable. Scheme also permits variables to begin with capital letters, or to consist solely of the single character `_`; but the other languages reserve these terms for special purposes.
+Our [[syntax for variables|topics/week1_kapulet_intro#variables]] in Kapulet is close to that in the other languages. Haskell and OCaml differ only in that they do not permit trailing `?` or `!`; however, they do permit trailing `'`s (and even permit `'`s *in the middle* of a variable too, which Kapulet does not). Scheme permits all of these characters, plus many more punctuation symbols as well, to occur anywhere in a variable. Scheme also permits variables to begin with capital letters, or to consist solely of the single character `_`; but the other languages reserve these terms for special purposes.
In addition to the variables made of letters (more properly, of alphanumerics), Haskell and OCaml and Kapulet also permit some variables made exclusively of punctuation symbols, like `<` or Haskell's `>=>` and `<$>`. In Haskell, these always have infix syntax, and the variables made of letters never do. (But the former can have their infix syntax suppressed with parentheses, and the latter can be "flagged" to temporarily take on infix syntax, as we'll discuss below.)
@@ -157,8 +157,27 @@ Here the last displayed line will fail, because `add` expects as its argument a
Kapulet essentially works like OCaml and Haskell; though for pedagogical reasons we started out by introducing uncurried definitions, rather than the *curried* definitions those other languages predominantly use.
+Here are some interesting functions we can define in Kapulet. See [[below|rosetta1#curried-patterns]] for the pattern syntax used here.
+
+ # Kapulet
+ let
+ curry match lambda f. lambda x y. f (x, y);
+ uncurry match lambda g. lambda (x, y). g x y ;
+ uncurried_flip match lambda f. lambda (y, x). f (x, y)
+ curried_flip match lambda g. lambda y x. g x y;
+ in ...
+
+The function `curry` takes as an argument a function `f` that expects its arguments *uncurried*, and returns instead `lambda x y. f (x, y)`, a function that expects its arguments *curried* --- but then does with them whatever `f` does. Going in the other direction, the function `uncurry` takes a function `g` that expects its arguments *curried*, and returns instead a function that expects its arguments *uncurried* --- but then does with them whatever `g` does.
+
+The function `uncurried_flip` takes as an argument again an uncurried function `f`, and returns another function that also expects its arguments uncurried, but that expects them in the other order. `curried_flip` transforms a curried function `g` in the analogous way. These are both different from the function `swap` we defined in the [[course notes|topics/week1_kapulet_advanced#functions]] as:
+
+ lambda (x, y) = (y, x)
+
+*That* function operates on a tuple and returns another tuple. The `..._flip` functions operate on functions, and transform them into other functions that expect their arguments in a different order.
+
+
-[[As we mentioned in the course notes|topics/week1_advanced_notes#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
+[[As we mentioned in the course notes|topics/week1_kapulet_advanced#sections]], in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
# Kapulet
let
@@ -402,7 +421,7 @@ All of the functions listed as missing from the official Scheme standard can be
### Tuples
-The course notes [[already mentioned|topics/week1#lightweight]] that Kapulet has a "lightweight" notion of tuples, called multivalues and written `(10, x)`, as well as a heavier notion written `Pair (10, x)`. The latter is what corresponds to the tuples in Haskell and OCaml. They don't have any explicit notation for Kapulet's "lightweight" tuples (though they exist behind the scenes in OCaml and explain some of its otherwise puzzling behavior). There are good reasons for introducing this additional complexity in Kapulet, but this is not the place to explain them.
+The course notes [[already mentioned|topics/week1_kapulet_intro#lightweight]] that Kapulet has a "lightweight" notion of tuples, called multivalues and written `(10, x)`, as well as a heavier notion written `Pair (10, x)`. The latter is what corresponds to the tuples in Haskell and OCaml. They don't have any explicit notation for Kapulet's "lightweight" tuples (though they exist behind the scenes in OCaml and explain some of its otherwise puzzling behavior). There are good reasons for introducing this additional complexity in Kapulet, but this is not the place to explain them.
All of these languages have notions of zero-length tuples, as well as pairs, triples, and the like. (In Kapulet's case, there are both the 0-length multivalue `()` and heavier counterparts.)
@@ -444,9 +463,9 @@ Kapulet's `(comp)`, `odd?`, `even?`, and `swap` are Haskell's `( . )`, `odd`, `e
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): `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_kapulet_intro#lightweight]] or "lightweight tuples" and Haskell's tuples): `id`, `const`, `curry`, `uncurry`. Kapulet's `curried_flip` is Haskell's `flip`. 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.)
+Kapulet and Haskell both have `( $ )`, which was explained [[in the course notes|topics/week1_kapulet_advanced#dollar]]. OCaml expresses this as `( @@ )`. (OCaml also uses `|>` to express the converse operation: `f x`, `f @@ x` and `x |> f` all mean the same.)
@@ -492,7 +511,7 @@ Note there is no closing `end` or `}`. You can enclose the whole expression in p
| 1 -> result1
| x -> resultx
-The syntax for [[guards|topics/week1_advanced_notes#guards]] and [[as-patterns|topics/week1_advanced_notes#as-patterns]] also only varies slightly between these languages:
+The syntax for [[guards|topics/week1_kapulet_advanced#guards]] and [[as-patterns|topics/week1_kapulet_advanced#as-patterns]] also only varies slightly between these languages:
# Kapulet
case some_expression of
@@ -605,6 +624,7 @@ This is similar to Scheme's `when` construction. Kapulet and Haskell have no ana
### Lambda expressions
+
In Kapulet you write λ expressions (sometimes called "anonymous functions") with a prefix of either λ or the spelled-out `lambda`. That's followed by one or more patterns, separated by spaces, then a period, then a single expression which makes up the body of the function. When there are multiple patterns, the function expressed is *curried*, thus:
lambda (x, y) z. result
@@ -791,7 +811,7 @@ Haskell's "toplevel interpreter" (ghci) permits a syntactic form that looks supe
let x = 2
x
-but under the covers something quite different is happening. (Specifically, you're working "inside the IO Monad", except that in this special context, expressions like `x` that don't evaluate to monadic values are permitted and evaluated. We don't expect that you will understand yet what any of this means.) If you're writing *in a file* that you want Haskell to interpret or compile, on the other hand, you have to do something a bit different (which you can't easily also do at the toplevel in ghci). [[Recall|topics/week1_advanced_notes#funct-declarations]] the shortcut by which we permitted:
+but under the covers something quite different is happening. (Specifically, you're working "inside the IO Monad", except that in this special context, expressions like `x` that don't evaluate to monadic values are permitted and evaluated. We don't expect that you will understand yet what any of this means.) If you're writing *in a file* that you want Haskell to interpret or compile, on the other hand, you have to do something a bit different (which you can't easily also do at the toplevel in ghci). [[Recall|topics/week1_kapulet_advanced#funct-declarations]] the shortcut by which we permitted:
# Kapulet
let