note what's in progress
[lambda.git] / rosetta.mdwn
1 ## Can you summarize the differences between your made-up language and Scheme, OCaml, and Haskell? ##
2
3 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.
4
5 Also, if you want to read code written outside this class, or have others read your code, for these reasons too you'll need to make the shift over to one of the established languages.
6
7 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.)
8
9 [[!toc levels=2]]
10
11 ### Comments
12
13     ...  # this is a comment in Kapulet, that goes until the end of the line
14
15     ...  ; this is a comment in Scheme, that goes until the end of the line
16
17     ...  -- this is a comment in Haskell, that goes until the end of the line
18
19 Note that for Haskell's comments, the `--` must be immediately followed by something like a space or a letter. `-->` does not begin a comment; it's a legal operator symbol.
20
21 OCaml doesn't have comments of that sort. It only has "block" comments like this:
22
23     (* ... *)
24
25 which may last for several lines. These comments *nest*, so that:
26
27     (* ... (* inner *) ... *)
28
29 is a single comment.
30
31 Haskell also has block comments, though it `{- writes them differently -}`.
32 Haskell's block comments also nest.
33
34 Racket and Scheme also have block comments, though they `#| write them differently |#`.
35 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.)
36
37
38
39 ### Variable names
40
41 % 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).
42
43
44
45 ### Infix operators and parentheses
46
47
48 Kapulet, OCaml, and Haskell all understand some expressions like `+` to be infix operators. So you would write:
49
50     1 + 2
51
52 not:
53
54     + 1 2
55
56 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`.
57
58 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:
59
60     3 `mod` 2
61
62 But without the `` ` ``, you'd have to write: `mod 3 2`.
63
64 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:
65
66     (+ 3 2)
67
68 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:
69
70     ((+) 3 2)
71
72 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.
73
74 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 `'`.)
75
76 % Parentheses have other roles in Scheme, too.
77
78 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:
79
80     (* OCaml *)
81     let add  = fun x y -> x + y in
82     let add2 = add 2 in
83         add2 3
84     ;;
85
86 will result in `5`.
87
88 In Scheme, the default would be to define `add` like this:
89
90     (define add (lambda (x y) (+ x y)))
91
92 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:
93
94     (define curried_add (lambda (x) (lambda (y) (+ x y))))
95     (define add2 (curried_add 2))
96     (add2 3)
97
98 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.
99
100 OCaml and Haskell also permit defining functions in uncurried form:
101
102     (* OCaml *)
103     let add  = fun (x, y) -> x + y in
104     let add2 = fun add 2 in ...
105
106 Here the last displayed line will fail, because `add` expects as its argument a tuple of two numbers.
107
108 Kapulet is close to OCaml and Haskell; though for pedagogical reasons I started out introducing uncurried definitions.
109
110 As we mentioned, in Kapulet, OCaml, and Haskell, there is a shorthand that enables you to write things like:
111
112     # Kapulet
113     let
114       ten_minus match lambda x. 10 - x;
115       and_ys    match lambda x. x & ys
116     in (ten_minus, and_ys)
117
118 like this:
119
120     # Kapulet
121     let
122       ten_minus match (10 - );
123       and_ys    match ( & ys)
124     in (ten_minus, and_ys)
125
126 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.
127
128 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:
129
130     # Kapulet
131     (0 - 2)
132     ( - 2)         # ( - 2) 10 == 8
133     (0 - )
134     ( - ) (5, 3)
135     
136
137 and here are their translations into Haskell:
138
139     -- Haskell
140     ( -2 )
141     (subtract 2)  -- subtract 2 10 == 8
142     negate        -- (0 - ) also works
143     ( - ) 5 3
144
145 OCaml expresses `(0 - )` or `negate` as `~-`. You can write `3 * (0 - 2)` in OCaml as either `3 * ( -2 )` or as `3 * ~-2`.
146
147 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."
148
149
150
151 ### More to come ...
152
153 (This page is being worked on...)
154
155
156 ## Offsite Readings comparing Scheme, OCaml, and Haskell ##
157
158 *   [Haskell for OCaml Programmers](http://science.raphael.poss.name/haskell-for-ocaml-programmers.pdf)
159 *   [Introduction to OCaml for Haskellers](http://foswiki.cs.uu.nl/foswiki/pub/Stc/BeyondFunctionalProgrammingInHaskell:AnIntroductionToOCaml/ocaml.pdf), [another](http://blog.ezyang.com/2010/10/ocaml-for-haskellers/)
160 *   Haskell Wiki on [OCaml](https://wiki.haskell.org/OCaml)
161 *   [ML Dialects and Haskell](http://hyperpolyglot.org/ml)
162 *   [Differences between Haskell and SML?](http://www.quora.com/What-are-the-key-differences-between-Haskell-and-Standard-ML?browse)
163 *   [Comparing SML to OCaml](http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html)
164
165
166
167 ## Why did you name these pages "Rosetta"? ##
168
169 The [Rosetta Stone](https://en.wikipedia.org/wiki/Rosetta_Stone) is a famous slab discovered during Napoleon's invasion of Egypt, that had the same decree written in ancient Greek (which modern scholars understood) and two ancient Egyptian scripts (which they didn't). The slab enabled us to recover understanding of those Egyptian scripts; and has since come to be a symbol for the simultaneous expression of a single idea in multiple languages. A number of websites do this for various programming languages:
170
171 <table><th>
172 <td>Scheme
173 <td>OCaml
174 <td>Haskell
175 <tr>
176 <td rowspan=10>&nbsp;
177 <td><a href="http://rosettacode.org/wiki/Category:Scheme">Rosetta Code</a>
178 <td><a href="http://rosettacode.org/wiki/Category:OCaml">Rosetta Code</a>
179 <td><a href="http://rosettacode.org/wiki/Category:Haskell">Rosetta Code</a>
180 <tr>
181 <td><a href="http://pleac.sourceforge.net/pleac_guile/index.html">PLEAC</a>
182 <td><a href="http://pleac.sourceforge.net/pleac_ocaml/index.html">PLEAC</a>
183 <td><a href="http://pleac.sourceforge.net/pleac_haskell/index.html">PLEAC</a>
184 <tr>
185 <td>n/a
186 <td colspan=2 align=center><hr><a href="http://langref.org/ocaml+haskell/solved">langref.org</a>
187 <tr>
188 <td><a href="http://www.codecodex.com/wiki/Category:Scheme">code codex</a>
189 <td><a href="http://www.codecodex.com/wiki/Category:Objective_Caml">code codex</a>
190 <td><a href="http://www.codecodex.com/wiki/Category:Haskell">code codex</a>
191 <tr>
192 <td><a href="http://community.schemewiki.org/?ninety-nine-scheme-problems">99 problems</a>
193 <td><a href="http://ocaml.org/learn/tutorials/99problems.html">99 problems</a>
194 <td><a href="https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems">99 problems</a>
195 </table>
196
197 See also the [Project Euler](https://projecteuler.net/) programming challenges.