translating tweaks
authorJim Pryor <profjim@jimpryor.net>
Sat, 4 Dec 2010 14:22:39 +0000 (09:22 -0500)
committerJim Pryor <profjim@jimpryor.net>
Sat, 4 Dec 2010 14:22:39 +0000 (09:22 -0500)
Signed-off-by: Jim Pryor <profjim@jimpryor.net>
translating_between_OCaml_Scheme_and_Haskell.mdwn

index 7b66cb3..171f644 100644 (file)
@@ -1,6 +1,6 @@
 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 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 translatio nmanual](http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html).
+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 translatiomanual](http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html).
 
 In some respects these languages are closer to Scheme than to Haskell: Scheme, OCaml and SML all default to call-by-value evaluation order, and all three have native syntax for mutation and other imperative idioms (though that's not central to their design). Haskell is different in both respects: the default evaluation order is call-by-name (strictly speaking, it's "call-by-need", which is a more efficient cousin), and the only way to have mutation or the like is through the use of monads.
 
 
 In some respects these languages are closer to Scheme than to Haskell: Scheme, OCaml and SML all default to call-by-value evaluation order, and all three have native syntax for mutation and other imperative idioms (though that's not central to their design). Haskell is different in both respects: the default evaluation order is call-by-name (strictly speaking, it's "call-by-need", which is a more efficient cousin), and the only way to have mutation or the like is through the use of monads.
 
@@ -205,10 +205,10 @@ So we have:
                class Eq a where
                  (==)    :: a -> a -> Bool
 
                class Eq a where
                  (==)    :: a -> a -> Bool
 
-       This declares the type-class `Eq`; in order to belong to this class, a type `a` will have to supply its own implementation of the function ==, with the type a -> a -> Bool. Here is how the `Integer` class signs up to join the type-class:
+       This declares the type-class `Eq`; in order to belong to this class, a type `a` will have to supply its own implementation of the function `==`, with the type `a -> a -> Bool`. Here is how the `Integer` class signs up to join this type-class:
 
                instance Eq Integer where
 
                instance Eq Integer where
-                 x == y  =  ...
+                 x == y  =  ... some definition for the Integer-specific version of that function here ...
 
        Type expressions can be conditional on some of their parameters belonging to certain type-classes. For example:
 
 
        Type expressions can be conditional on some of their parameters belonging to certain type-classes. For example:
 
@@ -225,7 +225,7 @@ So we have:
 
        says that if `a` belongs to the typeclass `Eq`, then so too does `Tree a`, and in such cases here is the implementation of `==` for `Tree a`...
 
 
        says that if `a` belongs to the typeclass `Eq`, then so too does `Tree a`, and in such cases here is the implementation of `==` for `Tree a`...
 
-*      OCaml doesn't have type-classes. You can do soemthing similar with OCaml modules that take are parameterized on other modules. Again, [see here](/code/tree_monadize.ml) for an example.
+*      OCaml doesn't have type-classes. You can do something similar with OCaml modules that take are parameterized on other modules. Again, [see here](/code/tree_monadize.ml) for an example.
 
 
 *      Some specific differences in how certain types are expressed. This block in Haskell:
 
 
 *      Some specific differences in how certain types are expressed. This block in Haskell:
@@ -237,7 +237,7 @@ So we have:
                Prelude> let x = () :: ()
                Prelude> let x = (1, True) :: (Int, Bool)
 
                Prelude> let x = () :: ()
                Prelude> let x = (1, True) :: (Int, Bool)
 
-corresponds to this block in OCaml:
+       corresponds to this block in OCaml:
 
                # type 'a option = None | Some of 'a;;
                type 'a option = None | Some of 'a
 
                # type 'a option = None | Some of 'a;;
                type 'a option = None | Some of 'a
@@ -299,14 +299,17 @@ corresponds to this block in OCaml:
 
                List.map (fun x -> x * x) (List.filter odd [1..10]);;
 
 
                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 chars.) 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:
 
 
        Haskell uses the operator `++` for appending both strings and lists (since Haskell strings are just one kind of list). OCaml uses different operators:
 
-               "string1" ^ "string2"
-               ['s';'t'] @ ['r';'i';'n';'g']
-               (* or equivalently *)
-               List.append ['s';'t'] ['r';'i';'n';'g']
+               # "string1" ^ "string2";;
+               - : string = "string1string2"
+               # ['s';'t'] @ ['r';'i';'n';'g'];;
+               - : char list = ['s'; 't'; 'r'; 'i'; 'n'; 'g']
+               # (* or equivalently *)
+                 List.append ['s';'t'] ['r';'i';'n';'g'];;
+               - : char list = ['s'; 't'; 'r'; 'i'; 'n'; 'g']
 
 
 #Let and Where#
 
 
 #Let and Where#
@@ -369,27 +372,27 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
 *      In Haskell one says:
 
                -- declare a record type
 *      In Haskell one says:
 
                -- declare a record type
-               data Color = C { red, green, blue :: Int }
+               data Color = Col { red, green, blue :: Int }
                -- create a value of that type
                -- create a value of that type
-               let c = C { red = 0, green = 127, blue = 255 }
+               let c = Col { red = 0, green = 127, blue = 255 }
 
        In OCaml one says instead:
 
 
        In OCaml one says instead:
 
-               type color = { red : int; green : int; blue : int};;
+               type color = { red : int; green : int; blue : int };;
                let c = { red = 0; green = 127; blue = 255 }
 
                let c = { red = 0; green = 127; blue = 255 }
 
-       Notice that OCaml doesn't use any value constructor `C`. The record syntax `{ red = ...; green = ...; blue = ... }` is by itself the constructor. The record labels `red`, `green`, and `blue` cannot be re-used for any other record type.
+       Notice that OCaml doesn't use any value constructor `Col`. The record syntax `{ red = ...; green = ...; blue = ... }` is by itself the constructor. The record labels `red`, `green`, and `blue` cannot be re-used for any other record type.
 
 *      In Haskell, one may have multiple constructors for a single record type, and one may re-use record labels within that type, so long as the labels go with fields of the same type:
 
                data FooType = Constructor1 {f :: Int, g :: Float} | Constructor2 {f :: Int, h :: Bool}
 
 
 *      In Haskell, one may have multiple constructors for a single record type, and one may re-use record labels within that type, so long as the labels go with fields of the same type:
 
                data FooType = Constructor1 {f :: Int, g :: Float} | Constructor2 {f :: Int, h :: Bool}
 
-*      In Haskell, one can extract the field of a record like this:
+*      In Haskell, one can extract a single field of a record like this:
 
 
-               let c = C { red = 0, green = 127, blue = 255 }
+               let c = Col { red = 0, green = 127, blue = 255 }
                in red c    -- evaluates to 0
 
                in red c    -- evaluates to 0
 
-       In OCaml:
+       In OCaml one says:
 
                let c = { red = 0; green = 127; blue = 255 }
                in c.red    (* evaluates to 0 *)
 
                let c = { red = 0; green = 127; blue = 255 }
                in c.red    (* evaluates to 0 *)
@@ -397,7 +400,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
 *      In both languages, there is a special syntax for creating a copy of an existing record, with some specified fields altered. In Haskell:
 
                let c2 = c { green = 50, blue = 50 }
 *      In both languages, there is a special syntax for creating a copy of an existing record, with some specified fields altered. In Haskell:
 
                let c2 = c { green = 50, blue = 50 }
-               -- evaluates to C { red = red c, green = 50, blue = 50 }
+               -- evaluates to Col { red = red c, green = 50, blue = 50 }
 
        In OCaml:
 
 
        In OCaml:
 
@@ -406,7 +409,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
 
 *      One pattern matches on records in similar ways. In Haskell:
 
 
 *      One pattern matches on records in similar ways. In Haskell:
 
-               let C { red = r, green = g } = c
+               let Col { red = r, green = g } = c
                in r
 
        In OCaml:
                in r
 
        In OCaml:
@@ -416,11 +419,11 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
 
        In Haskell:
 
 
        In Haskell:
 
-               makegray c@(C { red = r} ) = c { green = r, blue = r }
+               makegray c@(Col { red = r } ) = c { green = r, blue = r }
 
        is equivalent to:
 
 
        is equivalent to:
 
-               makegray c = let C { red = r } = c
+               makegray c = let Col { red = r } = c
                             in { red = r, green = r, blue = r }
 
        In OCaml it's:
                             in { red = r, green = r, blue = r }
 
        In OCaml it's:
@@ -486,7 +489,7 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
                  | x' when x' = 0 -> 0
                  | _ -> -1
 
                  | x' when x' = 0 -> 0
                  | _ -> -1
 
-*      In Haskell the equality comparison operator is `==`, and the non-equality operator is `/=`. In OCaml, `==` expresses "physical identity", which has no analogue in Haskell because Haskell has no mutable types. See our discussion of "Four grades of mutable involvement" in the [[Week9]] notes. In OCaml the operator corresponding to Haskell's `==` is just `=`, and the corresponding non-equality operator is `<>`.
+*      In Haskell the equality comparison operator is `==`, and the non-equality operator is `/=`. In OCaml, `==` expresses "physical identity", which has no analogue in Haskell because Haskell has no mutable types. See our discussion of "Four grades of mutation involvement" in the [[Week9]] notes. In OCaml the operator corresponding to Haskell's `==` is just `=`, and the corresponding non-equality operator is `<>`.
 
 *      In both Haskell and OCaml, one can use many infix operators as prefix functions by parenthesizing them. So for instance:
 
 
 *      In both Haskell and OCaml, one can use many infix operators as prefix functions by parenthesizing them. So for instance:
 
@@ -494,10 +497,10 @@ Haskell and OCaml both have `records`, which are essentially just tuples with a
 
        will work in both languages. One notable exception is that in OCaml you can't do this with the list constructor `::`:
 
 
        will work in both languages. One notable exception is that in OCaml you can't do this with the list constructor `::`:
 
-       # (::) 1 [1;2];;
-       Error: Syntax error
-       # (fun x xs -> x :: xs) 1 [1; 2];;
-       - : int list = [1; 1; 2]
+               # (::) 1 [1;2];;
+               Error: Syntax error
+               # (fun x xs -> x :: xs) 1 [1; 2];;
+               - : int list = [1; 1; 2]
 
 *      Haskell also permits two further shortcuts here that OCaml has no analogue for. In Haskell, in addition to writing:
 
 
 *      Haskell also permits two further shortcuts here that OCaml has no analogue for. In Haskell, in addition to writing: