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. Here's another comparison.

In some respects OCaml and SML 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.

On both sides, however, the non-default evaluation order can also be had by using special syntax. And in other respects, OCaml and SML are more like Haskell than they are like Scheme. For example, OCaml and SML and Haskell all permit you to declare types and those types are statically checked: that is, your program won't even start to be interpreted unless all the types are consistent. In Scheme, on the other hand, type-checking only happens when your program is running, and the language is generally much laxer about what it accepts as well-typed. (There's no problem having a list of mixed numbers and booleans, for example... and you don't need to wrap them in any sum type to do so.)

Additionally, the syntax of OCaml and SML is superficially much closer to Haskell's than to Scheme's.

    -- this is a single line comment in Haskell

{- this
is a multiline

(* this is a single or multiline
comment in OCaml *)

; this is a single line comment in Scheme

#| this is a
multiline comment
in Scheme |#

#;(this is
(another way to
(comment out (a block) (of Scheme code))))


• 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.

We've written some advice on how to do some OCaml-ish and Haskell-ish things in Scheme, and how to get Scheme-ish continuations in OCaml, on another page.

## 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 ints 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 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;


In printed media, Haskell type variables are often written using Greek letters, like this:

type Either α β = Left α | Right β


Some terminology: in this type declaration, Either is known as a type-constructor, since it takes some types α and β as arguments and yields a new type. We call Left α one of the variants for the type Either α β. Left and Right are known as value constructors or data constructors or just constructors. You can use Left in any context where you need a function, for example:

map Left [1, 2]


In OCaml, value constructors are still capitalized, but type names are lowercase. Type variables take the form 'a instead of a, and if there are multiple type variables, they're not Curried but instead have to be grouped in a tuple. The syntax for whether they appear first or second is also somewhat different. So we have instead:

type ('a,'b) either = Left of 'a | Right of 'b;;
type ('a,'b) foo_type = Foo_constructor1 of 'a * 'b | Foo_constructor2 of 'a * 'b;;


In OCaml, constructors aren't full-fledged functions, so you need to do this instead:

List.map (fun x -> Left x) [1; 2]


Apart from these differences, there are many similarities between Haskell's and OCaml's use of constructors. For example, in both languages you can do:

let Left x = Left 1 in x + 1

• In addition to the data keyword, Haskell also sometimes uses type and newtype to declare types. type is used just to introduce synonyms. If you say:

type Weight = Integer
type Person = (Name, Address)    -- supposing types Name and Address to be declared elsewhere


then you can use a value of type Integer wherever a Weight is expected, and vice versa.

newtype and data on the other hand, create genuinely new types. newtype is basically just an efficient version of data that you can use in special circumstances. newtype must always take one type argument and have one value constructor. For example:

newtype PersonalData a = PD a


You could also say:

data PersonalData2 a = PD2 a


And data also allows multiple type arguments, and multiple variants and value constructors.

OCaml just uses the one keyword type for all of these purposes:

type weight = int;;
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 PersonalData3 a = PersonalData3 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)


One does this for example when defining monad transformers---the type constructor ReaderT takes some base monad's type constructor as an argument.

The way to do this this in OCaml is less straightforward. You have to use parameterized modules. See our Ramble on Monads and modules for discussion.

• So here's a summary of how some different type declarations look in Haskell:

data Pretty1 a b = Lovely a | Cute b ClothingModule.ButtonType
newtype Pretty2 a b = Pretty2 a b Int
type Pretty3 a b = (a, b)


and in OCaml:

type ('a,'b) pretty1 = Lovely of 'a | Cute of 'b * ClothingModule.ButtonType
type ('a,'b) pretty2 = Pretty2 of 'a * 'b * int
type ('a,'b) pretty3 = 'a * 'b


There's also:

-- Haskell
newtype Pretty4 a b = Pretty4 { unPretty a }

(* OCaml *)
type ('a,'b) pretty4 = Pretty4 of 'a
(* or *)
type ('a,'b) pretty4 = { pretty4: 'a }


We will discuss record types further below.

• Haskell has a notion of type-classes. They look like this:

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 this type-class:

instance Eq Integer where
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:

elem      :: (Eq a) => a -> [a] -> Bool


says that the function elem is only defined over types a that belong to the type-class Eq. For such types a, elem has the type a -> [a] -> Bool.

Similarly:

instance (Eq a) => Eq (Tree a) where
Leaf a         == Leaf b          =  a == b
(Branch l1 r1) == (Branch l2 r2)  =  (l1==l2) && (r1==r2)
_              == _               =  False


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...

We also discuss type-classes briefly in our Ramble on Monads and modules for discussion.

• OCaml doesn't have type-classes. You can do something similar with OCaml modules that take are parameterized on other modules. See the page just linked for discussion.

• Some specific differences in how certain types are expressed. This block in Haskell:

Prelude> type Maybe a = Nothing | Just a
Prelude> let x = [] :: [Int]
Prelude> :t x
x :: [Int]
Prelude> let x = () :: ()
Prelude> let x = (1, True) :: (Int, Bool)


corresponds to this block in OCaml:

# type 'a option = None | Some of 'a;;
type 'a option = None | Some of 'a
# let (x : int list) = [];;
val x : int list = []
# let (x : unit) = ();;
val x : unit = ()
# let (x : int * bool) = (1, true);;
val x : int * bool = (1, true)

• Haskell has a plethora of numerical types, including the two types Int (integers limited to a machine-dependent range) and Integer (unbounded integers). The same arithmetic operators (+ and so on) work for all of these. OCaml also has several different numerical types (though not as many). In OCaml, by default, one has to use a different numerical operator for each type:

# 1 + 2;;
- : int = 3
# 1.0 + 2.0;;
Error: This expression has type float but an expression was expected of type int
# 1.0 +. 2.0;;
- : float = 3.


However the comparison operators are polymorphic. You can equally say:

# 1 = 2;;
- : bool = false
# 1.0 = 2.0;;
- : bool = false
# 2 > 1;;
- : bool = true
# 2.0 > 1.0;;
- : bool = true


But you must still apply these operators to expressions of the same type:

# 2.0 > 1;;
Error: This expression has type int but an expression was expected of type float

• We'll discuss differences between Haskell's and OCaml's record types below.

## Lists, Tuples, Unit, Booleans

• As noted above, Haskell describes the type of a list of Ints as [Int]. OCaml describes it as int list. Haskell describes the type of a pair of Ints 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.

• Haskell describes the boolean type as Bool and its variants are True and False. OCaml describes the type as bool and its variants are true and false. This is an inconsistency in OCaml: other value constructors must always be capitalized.

• As noted above, in Haskell one builds up a list by saying 1 : [2, 3]. In OCaml one says 1 :: [2; 3]. In Haskell, one can test whether a list is empty with either:

lst == []
null lst


In OCaml, there is no predefined null or isempty function. One can still test whether a list is empty using the comparison lst = []. Our Juli8 libraries also provide List.is_null.

• 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.

[ x * x | x <- [1..10], odd x]


In OCaml, one has to write this out longhand:

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.

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";;
- : string = "string1string2"
# ['s';'t'] @ ['r';'i';'n';'g'];;
- : char list = ['s'; 't'; 'r'; 'i'; 'n'; 'g']
# (* note that Haskell uses the @ symbol differently, for "as-patterns", discussed below *)
(* equivalently, in OCaml you can say *)
List.append ['s';'t'] ['r';'i';'n';'g'];;
- : char list = ['s'; 't'; 'r'; 'i'; 'n'; 'g']


## Let and Where

foo x =
let result1 = x * x
result2 = x + 1
in result1 + result2


and:

foo x = result1 + result2
where result1 = x * x
result2 = x + 1


OCaml permits only:

let foo x =
let result1 = x * x
in let result2 = x + 1
in result1 + result2;;


## Patterns

• In OCaml:

# let (x, y) as both = (1, 2)
in (both, x, y);;
- : (int * int) * int * int = ((1, 2), 1, 2)


let both@(x,y) = (1, 2)
in (both, x, y)

• In OCaml:

match list_expression with
| y::_ when odd y -> result1
| y::_ when y > 5 -> result2
| y::_ as whole -> (whole, y)
| [] -> result4


case list_expression of
(y:_) | odd y -> result1
| y > 5 -> result2
whole@(y:_) -> (whole, y)
[] -> result4


## Records

Haskell and OCaml both have records, which are essentially just tuples with a pretty interface. We introduced these in the wiki notes here.

The syntax for declaring and using these is a little bit different in the two languages.

-- declare a record type
data Color = Col { red, green, blue :: Int }
-- create a value of that type
let c = Col { red = 0, green = 127, blue = 255 }


type color = { red : int; green : int; blue : int };;
let c = { red = 0; green = 127; blue = 255 }


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 can extract a single field of a record like this:

let c = Col { red = 0, green = 127, blue = 255 }
in red c    -- evaluates to 0


In OCaml one says:

let c = { red = 0; green = 127; blue = 255 }
in c.red    (* evaluates to 0 *)

• 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 Col { red = red c, green = 50, blue = 50 }


In OCaml:

let c2 = { c with green = 50; blue = 50 }
(* evaluates to { red = c.red; green = 50; blue = 50 }

• One pattern matches on records in similar ways. In Haskell:

let Col { red = r, green = g } = c
in r


In OCaml:

let { red = r; green = g; _ } = c
in r


makegray c@(Col { red = r } ) = c { green = r, blue = r }


is equivalent to:

makegray c = let Col { red = r } = c
in { red = r, green = r, blue = r }


In OCaml it's:

# let makegray ({ red = r; _ } as c) = { c with green=r; blue=r };;
val makegray : color -> color = <fun>
# makegray { red = 0; green = 127; blue = 255 };;
- : color = {red = 0; green = 0; blue = 0}

• Records just give your types a pretty interface; they're entirely dispensable. Instead of:

type color = { red : int; green : int; blue : int };;
let c = { red = 0; green = 127; blue = 255 };;
let r = c.red;;


You could instead just use a more familiar data constructor:

type color = Color of (int * int * int);;
let c = Color (0, 127, 255);;


and then extract the field you want using pattern-matching:

let Color (r, _, _) = c;;
(* or *)
match c with Color (r, _, _) -> ...


(Or you could just use bare tuples, without the Color data constructor.)

The record syntax only exists because programmers sometimes find it more convenient to say:

... c.red ...


than to reach for those pattern-matching constructions.

## 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:

factorial    :: int -> int
factorial 0  =  1
factorial n  =  n * factorial (n-1)


In OCaml you must explicitly say when a function is recursive; and this would be written instead as:

let rec factorial (n : int) : int =
match n with
| 0 -> 1
| x -> x * factorial (x-1)


or:

let rec factorial : int -> int =
fun n -> match n with
| 0 -> 1
| x -> x * factorial (x-1)


or (though we recommend not using this last form):

let rec factorial : int -> int =
function
| 0 -> 1
| x -> x * factorial (x-1)


length         :: [a] -> Integer
length []      =  0
length (x:xs)  =  1 + length xs


In OCaml:

let rec length : 'a list -> int =
fun lst -> match lst with
| [] -> 0
| x::xs -> 1 + length xs


sign x | x >  0      = 1
| x == 0      = 0
| otherwise   = -1


In OCaml:

let sign x = match x with
| x' when x' > 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 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:

(+) 1 2


will work in both languages. One notable exception is that in OCaml you can't do this with the list constructor ::.

# (::);;
Error: Syntax error
# (::) 1 [1; 2];;
Error: Syntax error
# (fun x xs -> x :: xs) 1 [1; 2];;
- : int list = [1; 1; 2]


Another tricky issue is that whereas you can equally well write (+) or ( + ) in OCaml, writing (*) for the multiplication operator doesn't parse properly because of how OCaml processes comments. For that specific operation, you must write it with the extra spaces, as ( * ).

• Haskell also permits two further shortcuts here that OCaml has no analogue for. In Haskell, in addition to writing:

(>) 2 1


you can also write either of:

(2 >) 1
(> 1) 2


In OCaml one has to write these out longhand:

(fun y -> 2 > y) 1;;
(fun x -> x > 1) 2;;


Also, in Haskell, there's a special syntax for using what are ordinarily prefix functions as infix operators:

Prelude> elem 1 [1, 2]
True
Prelude> 1 elem [1, 2]
True


In OCaml one can't do that. There's only:

# List.mem 1 [1; 2];;
- : bool = true

• As mentioned before, data constructors like Just in Haskell can also be used as functions, for example they can be passed as arguments to higher order functions. This is not so in OCaml; you have to use fun x -> Some x. Juli8 provides a few such functions (Option.some, List.cons, Monad.LTree.leaf).

• In Haskell one writes anonymous functions like this:

\x -> x + 1


In OCaml it's:

fun x -> x + 1

• Haskell uses the period . as a composition operator:

g . f
-- same as
\x -> g (f x)


The Juli8 libraries provide % as a counterpart of this in OCaml. Otherwise in OCaml, one has to write it out longhand:

fun x -> g (f x)

• In Haskell, expressions like this:

g $f x y  are equivalent to: g (f x y)  (Think of the period in our notation for the untyped lambda calculus.) Note that this operator associates to the right: g$ f x $h y is g (f x (h y)) not g (f x) (h y). For complex reasons, OCaml can't make operators beginning with $ be right-associative, so they express this instead as:

g @@ f x y


OCaml also has the equivalent form:

f x y |> g

• The names of standard functions, and the order in which they take their arguments, may differ. In Haskell:

Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b


In OCaml:

# List.fold_right;;
- : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b = <fun>

• Some functions are predefined in Haskell but not in OCaml. Here are OCaml definitions for some common ones. (These are all predefined in Juli8, except that there id is ident.)

let id x = x;;
let const x _ = x;;
let flip f x y = f y x;;
let curry (f : ('a, 'b) -> 'c) = fun x y -> f (x, y);;
let uncurry (f : 'a -> 'b -> 'c) = fun (x, y) -> f x y;;


fst and snd (defined only on pairs) are provided in both languages. Haskell has head and tail for lists; these will raise an exception if applied to []. In OCaml the corresponding functions are List.hd and List.tl. (Juli8 renames them to List.head and List.tail, and also provides a few variations.) Many other Haskell list functions like length are available in OCaml as List.length, but OCaml's standard libraries are leaner that Haskell's.

• The until function in Haskell is used like this:

until (\l -> length l == 4) (1 : ) []
-- evaluates to [1,1,1,1]

until (\x -> x == 10) succ 0
-- evaluates to 10


This can be defined in OCaml as:

let rec until test f z =
if test z then z else until test f (f z)


Using Juli8, this can also be expressed as iter_while (non test) f z.

## 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.

• Like Scheme and most other languages, OCaml is by default eager. Laziness can be achieved either by using thunks:

# let eval_later1 () = 2 / 2;;
val eval_later1 : unit -> int = <fun>
# let eval_later2 () = 2 / 0;;
val eval_later2 : unit -> int = <fun>
# eval_later1 ();;
- : int = 1
# eval_later2 ();;
Exception: Division_by_zero.


or by using the special forms lazy and Lazy.force:

# let eval_later3 = lazy (2 / 2);;
val eval_later3 : int lazy_t = <lazy>
# Lazy.force eval_later3;;
- : int = 1
# eval_later3;;
- : int lazy_t = lazy 1


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.

Haskell has more built-in support for monads, but one can define the monads one needs in OCaml. (Or use the Monad libraries from Juli8.)

• In our seminar, we've been calling one monadic operation mid; in Haskell the same operation is called return. We've been calling another monadic operation mbind, sometimes used in prefix form, like this:

mbind xx k


We've also used the infix form:

xx >>= k


In Haskell, one uses the infix operator >>= to express bind instead:

xx >>= k

• Haskell also uses the operator >>, where xx >> yy means the same as xx >>= \_ -> yy. Juli8 provides this too.

• In Haskell, one can generally just use plain return and >>= and the interpreter will infer what monad you must be talking about from the surrounding type constraints. In OCaml, you generally need to be specific about which monad you're using. So in these notes, when mutiple monads are on the table, we've defined operations as reader_mid and reader_bind, and so on. Or, using the Juli8 libraries, you will say things like this:

Monad.List.(... >>= ...)


or like this:

module R = Monad.Reader(struct type env = ... end)
R.(... >>= ...)

• Haskell has a special syntax for working conveniently with monads. It looks like this. Assume xx yy and zz are values of some monadic type M a; then x y and w will be variables of type a:

do
x <- xx
y <- yy
zz
let w = foo x y
return w


This is equivalent in meaning to the following:

xx >>= \ x ->
yy >>= \ y ->
zz >>= \ _ ->
let w = foo x y
in return w


which can be translated straightforwardly into OCaml.

For more details, see:

• If you like the Haskell do-notation, there's a library 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:

main :: IO ()
main = do
let s = "hello world"
putStrLn s

main :: IO String
main = do
let s = "hello world"
putStrLn s
return s

main :: IO String
main = let s = "hello world"
in putStrLn s >> return s


OCaml permits you to mix side-effects with regular code, so you can just print, without needing to bring in any monad:

let main =
let s = "hello world"
in let () = print_endline s
in s;;


or:

let main =
let s = "hello world"
in print_endline s ; s;;