X-Git-Url: http://lambda.jimpryor.net/git/gitweb.cgi?p=lambda.git;a=blobdiff_plain;f=rosetta1.mdwn;h=eda1a9f8174929bea8e950731684afd8e2edb4c7;hp=bd2da5a3148d8a2f03796cc7cde282dcf7ed5602;hb=13d1f0c86e0ffb3fdeca38f40640160b579049aa;hpb=22d54c83731e9c0f0b741ab6f9f46da264a90c32 diff --git a/rosetta1.mdwn b/rosetta1.mdwn index bd2da5a3..eda1a9f8 100644 --- a/rosetta1.mdwn +++ b/rosetta1.mdwn @@ -78,7 +78,7 @@ These relations are written in Haskell and OCaml as `&&`, `||`, and `not`. (Hask The values that are written `'true` and `'false` in Kapulet are written in Haskell as `True` and `False`, and in OCaml as just `true` and `false`. (It'd be more consistent with OCaml's other naming policies for them to have said True and False, but they didn't.) These are written `#t` and `#f` in Scheme, but in Scheme in many contexts any value that isn't `#f` will behave as though it were `#t`, even values you might think are more "false-like", like `0` and the empty list. Thus `(if 0 'zero 'nope)` will evaluate to `'zero`. -Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`. +Some Scheme implementations, such as Racket, permit `#true` and `#false` as synonyms for `#t` and `#f`. (These aliases are also mandated in "version 7", r7rs, of the Scheme standard.) Scheme also recognizes the values `'true` and `'false`, but it treats `'false` as distinct from `#f`, and thus as a "truth-like" value, like all of its other values that aren't `#f`. Kapulet essentially took Scheme's `boolean` values and collapsed them into being a subtype of its `symbol` values. @@ -110,7 +110,13 @@ Scheme has no infix operators. It ruthlessly demands that all functions to be ap (+ 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: +and the like. Here is an example where the function to be applied is the result of evaluating a more complex expression: + + ((if #t + *) 3 2) + +which will evaluate to `5`, not `6`. + +In Scheme the parentheses are never optional and never redundant. In expressions like `(+ 3 2)`, 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) @@ -157,8 +163,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 @@ -444,9 +469,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_kapulet_intro#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 +517,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 +630,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 +817,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