manip trees: split off last section into monad_transformers
[lambda.git] / translating_between_OCaml_Scheme_and_Haskell.mdwn
index 20e10b5..d0f7442 100644 (file)
@@ -1,3 +1,5 @@
+[[!toc]]
+
 The functional programming literature tends to use one of four languages: Scheme, OCaml, Standard ML (SML), or Haskell. With experience, you'll grow comfortable switching between these. At the beginning, though, it can be confusing.
 
 The easiest translations are between OCaml and SML. These languages are both derived from a common ancestor, ML. For the most part, the differences between them are only superficial. [Here's a translation manual](http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html).
@@ -8,7 +10,7 @@ On both sides, however, the non-default evaluation order can also be had by usin
 
 Additionally, the syntax of OCaml and SML is superficially much closer to Haskell's than to Scheme's.
 
-##Comments, Whitespace, and Brackets##
+#Comments, Whitespace, and Brackets#
 
                -- this is a single line comment in Haskell
 
@@ -34,20 +36,23 @@ Additionally, the syntax of OCaml and SML is superficially much closer to Haskel
 *      In Haskell, a block of code can be bracketed with `{` and `}`, with different expressions separated by `;`. But usually one would use line-breaks and proper indentation instead. In OCaml, separating expressions with `;` has a different meaning, having to do with how side-effects are sequenced. Instead, one can bracket a block of code with `(` and `)` or with `begin` and `end`. In Scheme, of course, every parentheses is significant.
 
 
-##Scheme and OCaml##
+#Scheme and OCaml#
 
 *      You can [try Scheme in your web browser](http://tryscheme.sourceforge.net/). This is useful if you don't have Racket or another Scheme implementation installed---but don't expect it to have all the bells and whistles of a mature implementation!
 
 *      **Type Variants and Pattern Matching** If you want to reproduce this kind of OCaml code:
 
-               type lambda_expression = Var of char | Lam of char * lambda_expression | App of lambda_expression * lambda_expression;;
+               type lambda_expression = Var of char | Lam of char * lambda_expression | App of lambda_expression * lambda_expression;;
 
-               let rec free_vars (expr : lambda_expression) : char list =
+               let rec free_vars (expr : lambda_expression) : char list =
                  match expr with
                    | Var label -> [label]
                    | Lam (label, body) -> remove label (free_vars body)
                    | App (left, right) -> merge (free_vars left) (free_vars right);;
 
+               # free_vars (Lam ('x', (App (Var 'x', Var 'y'))));;
+               - : char list = ['y']
+
        in Scheme, you have two choices. First, the quick hack:
 
                ; we use the symbols 'var and 'lam as tags, and assume
@@ -65,7 +70,7 @@ Additionally, the syntax of OCaml and SML is superficially much closer to Haskel
 
        Second, you can create real datatypes and pattern-match on them. There are several tools for doing this. I'll describe the `define-datatype` and `cases` forms developed for the book *Essentials of Programming Languages* (EoPL) by Friedman and Wand.
 
-       (Alternatives include the `struct` form in Racket, see <http://docs.racket-lang.org/guide/define-struct.html>. Also `define-record-type` from srfi-9 and srfi-57; see also <http://docs.racket-lang.org/r6rs-lib-std/r6rs-lib-Z-H-7.html>.)
+       (Alternatives include [the `struct` form in Racket](http://docs.racket-lang.org/guide/define-struct.html). Also `define-record-type` from srfi-9 and srfi-57; see also [the r6rs libs](http://docs.racket-lang.org/r6rs-lib-std/r6rs-lib-Z-H-7.html).)
 
        Here is how the tools from EoPL work. You must begin your file either with `#lang eopl` or with the first two lines below:
 
@@ -83,8 +88,10 @@ Additionally, the syntax of OCaml and SML is superficially much closer to Haskel
                    (lam (label body) (remove label (free-vars body)))
                    (app (left right) (remove-duplicates (append (free-vars left) (free-vars right))))))
 
+               (free-vars (lam 'x (app (var 'x) (var 'y))))
+               ; evaluates to '(y)
 
-*      Scheme has excellent support for working with implicit or "first-class" **continuations**, using either `call/cc` or any of various delimited continuation operators. See <http://docs.racket-lang.org/reference/cont.html?q=shift&q=do#%28part._.Classical_.Control_.Operators%29>.
+*      Scheme has excellent support for working with implicit or "first-class" **continuations**, using either `call/cc` or any of various delimited continuation operators. See [the Racket docs](http://docs.racket-lang.org/reference/cont.html?q=shift&q=do#%28part._.Classical_.Control_.Operators%29).
 
        In Scheme you can use these forms by default (they're equivalent):
 
@@ -124,27 +131,27 @@ Additionally, the syntax of OCaml and SML is superficially much closer to Haskel
 
        There is also a library for using *undelimited* continuations in OCaml, but it's shakier than Oleg's delimited continuation library.
 
-We won't say any more about translating to and from Scheme.
+There are some more hints about Scheme [here](/assignment8/) and [here](/week1/). We won't say any more here.
 
 
-##Haskell and OCaml##
+
+#Haskell and OCaml#
 
 We will however try to give some general advice about how to translate between OCaml and Haskell.
 
 *      Again, it may sometimes be useful to [try Haskell in your web browser](http://tryhaskell.org/)
-*      There are many Haskell tutorials and textbooks available. This is probably the most actively developed: [Haskell Wikibook](http://en.wikibooks.org/wiki/Haskell)
-*      [Yet Another Haskell Tutorial](http://www.cs.utah.edu/~hal/docs/daume02yaht.pdf) (much of this excellent book has supposedly been integrated into the Haskell Wikibook)
-*      All About Monads has supposedly also been integrated into the Haskell Wikibook
+*      There are many Haskell tutorials and textbooks available. This is probably the most actively developed: [Haskell wikibook](http://en.wikibooks.org/wiki/Haskell)
+*      [Yet Another Haskell Tutorial](http://www.cs.utah.edu/~hal/docs/daume02yaht.pdf) (much of this excellent book has supposedly been integrated into the Haskell wikibook)
+*      All About Monads has supposedly also been integrated into the Haskell wikibook
 *      (A not-so-)[Gentle Introduction to Haskell](http://web.archive.org/web/http://www.haskell.org/tutorial/) (archived)
 *      [Learn You a Haskell for Great Good](http://learnyouahaskell.com/)
 
 
-#Type expressions#
+##Type expressions##
 
 *      In Haskell, you say a value has a certain type with: `value :: type`. You express the operation of prepending a new `int` to a list of `int`s with `1 : other_numbers`. In OCaml it's the reverse: you say `value : type` and `1 :: other_numbers`.
 
-*      In Haskell, type names and constructors both begin with capital letters, and type variables always appear after their constructors, in Curried form. And the primary term for declaring a new type is `data` (short for "abstract datatype").
-So we have:
+*      In Haskell, type names and constructors both begin with capital letters, and type variables always appear after their constructors, in Curried form. And the primary term for declaring a new type is `data` (short for [[!wikipedia algebraic data type]]). So we have:
 
                data Either a b = Left a | Right b;
                data FooType a b = Foo_constructor1 a b | Foo_constructor2 a b;
@@ -192,6 +199,12 @@ So we have:
                type person = name * address;;
                type 'a personal_data = PD of 'a;;
 
+*      When a type only has a single variant, as with PersonalData, Haskell programmers will often use the same name for both the type and the value constructor, like this:
+
+               data PersonalData a = PersonalData a
+
+       The interpreter can always tell from the context when you're using the type name and when you're using the value constructor.
+
 *      The type constructors discussed above took simple types as arguments. In Haskell, types are also allowed to take *type constructors* as arguments:
 
                data BarType t = Bint (t Integer) | Bstring (t string)
@@ -276,7 +289,7 @@ So we have:
 * We'll discuss differences between Haskell's and OCaml's record types below.
 
 
-#Lists, Tuples, Unit, Booleans#
+##Lists, Tuples, Unit, Booleans##
 
 *      As noted above, Haskell describes the type of a list of `Int`s as `[Int]`. OCaml describes it as `int list`. Haskell describes the type of a pair of `Int`s as `(Int, Int)`. OCaml describes it as `int * int`. Finally, Haskell uses `()` to express both the unit type and a value of that type. In OCaml, one uses `()` for the value and `unit` for the type.
 
@@ -289,7 +302,7 @@ So we have:
 
        In OCaml, there is no predefined `null` or `isempty` function. One can still test whether a list is empty using the comparison `lst = []`.
 
-*      In Haskell, the expression [1..5] is the same as [1,2,3,4,5], and the expression [0..] is a infinite lazily-evaluated stream of the natural numbers. In OCaml, there is no [1..5] shortcut, lists must be finite, and they are eagerly evaluated. It is possible to create lazy streams in OCaml, even infinite ones, but you have to use other techniques than the native list type.
+*      In Haskell, the expression `[1..5]` is the same as `[1,2,3,4,5]`, and the expression `[0..]` is a infinite lazily-evaluated stream of the natural numbers. In OCaml, there is no `[1..5]` shortcut, lists must be finite, and they are eagerly evaluated. It is possible to create lazy streams in OCaml, even infinite ones, but you have to use other techniques than the native list type.
 
 *      Haskell has *list comprehensions*:
 
@@ -299,7 +312,7 @@ So we have:
 
                List.map (fun x -> x * x) (List.filter odd [1..10]);;
 
-*      In Haskell, the expressions `"abc"` and `['a','b','c']` are equivalent. (Strings are just lists of chars.) In OCaml, these expressions have two different types.
+*      In Haskell, the expressions `"abc"` and `['a','b','c']` are equivalent. (Strings are just lists of `char`s.) In OCaml, these expressions have two different types.
 
        Haskell uses the operator `++` for appending both strings and lists (since Haskell strings are just one kind of list). OCaml uses different operators:
 
@@ -312,7 +325,7 @@ So we have:
                - : char list = ['s'; 't'; 'r'; 'i'; 'n'; 'g']
 
 
-#Let and Where#
+##Let and Where##
 
 *      Haskell permits both:
 
@@ -334,7 +347,7 @@ So we have:
                  in let result2 = x + 1
                  in result1 + result2;;
 
-#Patterns#
+##Patterns##
 
 *      In OCaml:
 
@@ -365,7 +378,7 @@ So we have:
                  [] -> result4
 
 
-#Records#
+##Records##
 
 Haskell and OCaml both have `records`, which are essentially just tuples with a pretty interface. The syntax for declaring and using these is a little bit different in the two languages.
 
@@ -434,7 +447,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
                - : color = {red = 0; green = 0; blue = 0}
 
 
-#Functions#
+##Functions##
 
 *      In Haskell functions are assumed to be recursive, and their types and applications to values matching different patterns are each declared on different lines. So we have:
 
@@ -591,7 +604,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
                  if test z then z else until test f (f z)
 
 
-#Lazy or Eager#
+##Lazy or Eager##
 
 *      As we've mentioned several times, Haskell's evaluation is by default *lazy* or "call-by-need" (that's an efficient version of "call-by-name" that avoids computing the same results again and again). In some places Haskell will force evaluation to be *eager* or "strict". This is done in several different ways; the symbols `!` and `seq` are signs that it's being used.
 
@@ -618,7 +631,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
        Notice in the last line the value is reported as being `lazy 1` instead of `<lazy>`. Since the value has once been forced, it won't ever need to be recomputed. The thunks are less efficient in this respect. Even though OCaml will now remember what `eval_later3` should be forced to, `eval_later3` is still type-distinct from a plain `int`.
 
 
-#Monads#
+##Monads##
 
 Haskell has more built-in support for monads, but one can define the monads one needs in OCaml.
 
@@ -657,6 +670,11 @@ Haskell has more built-in support for monads, but one can define the monads one
 
        which can be translated straightforwardly into OCaml.
 
+       For more details, see:
+
+       *       [Haskell wikibook on do-notation](http://en.wikibooks.org/wiki/Haskell/do_Notation)
+       *       [Do-notation considered harmful](http://www.haskell.org/haskellwiki/Do_notation_considered_harmful)
+
 *      If you like the Haskell do-notation, there's [a library](http://www.cas.mcmaster.ca/~carette/pa_monad/) you can compile and install to let you use something similar in OCaml.
 
 *      In order to do any printing, Haskell has to use a special `IO` monad. So programs will look like this: