From: jim
Date: Wed, 4 Feb 2015 16:13:24 +0000 (-0500)
Subject: note what's in progress
X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=commitdiff_plain;h=230e823a306b877955883dd136efc3aedcd82ef3;hp=bed1936312402da99421fec60b2ed3b915925d69;ds=sidebyside
note what's in progress
---
diff --git a/rosetta.mdwn b/rosetta.mdwn
index 8dd1391a..cef9a8b9 100644
--- a/rosetta.mdwn
+++ b/rosetta.mdwn
@@ -1,4 +1,4 @@
-## Can you summarize the differences between our made-up language and Scheme, OCaml, and Haskell? ##
+## 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.
@@ -6,6 +6,8 @@ Also, if you want to read code written outside this class, or have others read y
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.)
+[[!toc levels=2]]
+
### Comments
... # this is a comment in Kapulet, that goes until the end of the line
@@ -30,17 +32,125 @@ Haskell also has block comments, though it `{- writes them differently -}`.
Haskell's block comments also nest.
Racket and Scheme also have block comments, though they `#| write them differently |#`.
-These block comments also nest. Another form of block comments is `#;( ... )`. Those may contain nested parentheses, and extend until the next *matching* `)`. So prefixing `#;` to a complex parenthesized expression is a way to turn the whole thing into a comment. (These two comment styles aren't part of the official Scheme standard, but they widely implemented.)
+These block comments also nest. Another form of block comments is `#;( ... )`. Those may contain nested parentheses, and extend until the next *matching* `)`. So prefixing `#;` to a complex parenthesized expression is a way to turn the whole thing into a comment. (These two comment styles aren't part of the official Scheme standard, but they are widely implemented.)
+
+
+
+### Variable names
+
+% Haskell's division into letter-based vs operators. Each can be "flagged" to temporarily behave as though it belonged to the other syntactic category (see below).
+
+
+
+### Infix operators and parentheses
+
+
+Kapulet, OCaml, and Haskell all understand some expressions like `+` to be infix operators. So you would write:
+
+ 1 + 2
+
+not:
+
+ + 1 2
+
+Although all three of these languages permits you to enclose an infix operator in parentheses to make a *section*, which no longer has infix syntax. In Kapulet, `( + )` is the same as λ `(x, y). x + y`, whereas in OCaml and Haskell it's a *curried* function, which we can write (in Kapulet syntax) as λ `x y. x + y`.
+
+Kapulet and OCaml have some operators spelled with letters also taking infix syntax, such as `comp` in Kapulet or `mod` in OCaml. In Haskell, this is never the case: variables that begin with letters will only be treated as function-terms being applied to arguments when they're at the start of a list of expressions, and variables that are made of punctuation symbols, and not enclosed in parentheses, will only be treated as infix operators. However, Haskell permits you to temporarily flag a letter-based function name to behave like an infix operator, by enclosing it in `` ` `` marks. Thus in Haskell you can write:
+
+ 3 `mod` 2
+
+But without the `` ` ``, you'd have to write: `mod 3 2`.
+
+Scheme has no infix operators. It ruthlessly demands that all functions that are to be applied to arguments come at the start of a list of expressions, regardless of whether those functions are spelled using letters, punctuation symbols, or a mix of the two. Thus in Scheme one always writes:
+
+ (+ 3 2)
+
+and the like. Moreover, in Scheme parentheses are never optional and never redundant. In contexts like this, the parentheses are necessary to express that the function is being applied; `+ 3 2` on its own is not a complete Scheme expression. And if the `+` were surrounded by its own parentheses, as in:
+
+ ((+) 3 2)
+
+what that would mean would be that `+` is first being applied to *zero* arguments, which is different from not applying it all. (In Kapulet, OCaml, and Haskell, one would write that `f` is being applied to "zero arguments" like this: `f ()`.) Scheme helpfully defines the result of applying `+` to zero arguments to be `0`. So then `((+) 3 2)` would evaluate to whatever `(0 3 2)` does, and that's an error, because `0` is not a function.
+
+Note that `(0 3 2)`, although it *is*, qua expression, a list of numbers, does not evaluate to a list. To get an expression that *evaluates to* that list, you'd have to use `(list 0 3 2)` or `'(0 3 2)`. (Notice the initial `'`.)
+
+% Parentheses have other roles in Scheme, too.
+
+In Scheme, the default style for defining functions is as taking several arguments simultaneously, that is the *uncurried* style. In OCaml and Haskell, the default style is to define them *curried*. Curried functions can easily be partially applied:
+
+ (* OCaml *)
+ let add = fun x y -> x + y in
+ let add2 = add 2 in
+ add2 3
+ ;;
+
+will result in `5`.
+
+In Scheme, the default would be to define `add` like this:
+
+ (define add (lambda (x y) (+ x y)))
+
+Then you cannot say `(add 2)`, because `add` will be expecting two arguments, but you only supplied one. You can however define curried functions in Scheme, it's just more laborious:
+
+ (define curried_add (lambda (x) (lambda (y) (+ x y))))
+ (define add2 (curried_add 2))
+ (add2 3)
+
+will result in `5`. This is the best one can do in official Scheme, but there are various syntax extensions and macros out there to make it possible to write this sort of thing more succinctly.
+
+OCaml and Haskell also permit defining functions in uncurried form:
+
+ (* OCaml *)
+ let add = fun (x, y) -> x + y in
+ let add2 = fun add 2 in ...
+
+Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
+
+Kapulet is close to OCaml and Haskell; though for pedagogical reasons I started out introducing uncurried definitions.
+
+As we mentioned, in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
+
+ # Kapulet
+ let
+ ten_minus match lambda x. 10 - x;
+ and_ys match lambda x. x & ys
+ in (ten_minus, and_ys)
+
+like this:
+
+ # Kapulet
+ let
+ ten_minus match (10 - );
+ and_ys match ( & ys)
+ in (ten_minus, and_ys)
+
+There are just minor differences between these languages. First, OCaml doesn't have the `( + 10)` or `(10 + )` forms, but only the `( + )`. Second, as a special case, OCaml doesn't permit you to do this with its list-consing operator `::`. You have to write `fun x xs -> x :: xs`, not `( :: )`. Whereas in Kapulet `( & )`, `(x & )`, and `( & xs)` are all sections using its sequence-consing operator `&`; and in Haskell, `( : )`, `(x : )`, and `( & xs)` are the same.
+Thirdly, in Kapulet, `( - 10)` also expresses λ `x. x - 10` (consistently with `(10 - )`), but Haskell (and OCaml) treat this form differently, and interpret it as meaning the integer `- 10`. Here's how to express some things in Kapulet:
+ # Kapulet
+ (0 - 2)
+ ( - 2) # ( - 2) 10 == 8
+ (0 - )
+ ( - ) (5, 3)
+
+and here are their translations into Haskell:
+ -- Haskell
+ ( -2 )
+ (subtract 2) -- subtract 2 10 == 8
+ 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`.
+I know all these languages fairly well, and I still find this last issue difficult to keep track of. You may be starting to understand why I spoke of "warts."
+### More to come ...
+(This page is being worked on...)
## Offsite Readings comparing Scheme, OCaml, and Haskell ##