See also Stack Overflow, which is widely used by the OCaml community.
Num in OCaml and camlnum in Caml
Light./: addition is
thus +/. You build big numbers using conversion from
(small) integers or character strings. For printing in the toplevel,
a custom printer can be used. An example under OCaml is given below.
# #load "nums.cma";;
# open Num open Format;;
# let print_num ff n = fprintf ff "%s" (string_of_num n);;
val print_num : Format.formatter -> Num.num -> unit = <fun> # #install_printer print_num;;
# num_of_string "2/3";;
- : Num.num = 2/3 # let n = num_of_string "1/3" +/ num_of_string "2/3";;
val n : Num.num = 1 # let rec fact n = if n <= 0 then (num_of_int 1) else num_of_int n */ (fact (n - 1));;
val fact : int -> Num.num = <fun> # fact 100;;
- : Num.num = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
# let v = Array.make 3 0;;The physical sharing effect also applies to elements stored in vectors: if these elements are also vectors, the sharing of these vectors implies that modifying one of these elements modifies the others (see also the entry below).
val v : int array = [|0; 0; 0|] # let w = v;;
val w : int array = [|0; 0; 0|] # w.(0) <- 4;;
- : unit = () # v;;
- : int array = [|4; 0; 0|]
# let m = Array.make 2 (Array.make 3 0);;The allocation of a new array has two phases. First, the initial value is computed; then this value is written in each element of the new array. That's why the line which is allocated by
val m : int array array = [|[|0; 0; 0|]; [|0; 0; 0|]|] # m.(0).(0) <- 1;;
- : unit = () # m;;
- : int array array = [|[|1; 0; 0|]; [|1; 0; 0|]|]
Array.make 3
0 is unique and physically shared by all the lines of the array
m.make_matrix primitive that
builds the matrix with all elements equal to the initial value
provided. Alternatively, write the program that allocates a new line
for each line of your matrix. For instance:
# let matrix n m init = let result = Array.make n (Array.make m init) in for i = 1 to n - 1 do result.(i) <- Array.make m init done; result;;In the same vein, the
copy_vect primitive gives strange
results, when applied to matrices: you need to write a function that
explicitly copies each line of the matrix at hand:
# let copy_matrix m = let l = Array.length m in if l = 0 then m else let result = Array.make l m.(0) in for i = 0 to l - 1 do result.(i) <- Array.copy m.(i) done; result;;
# type color = Blue | White | Red;;The names
type color = Blue | White | Red # Blue;;
- : color = Blue
Blue, White and Red
are the constructors of the color type. One can define
functions on this type by pattern matching:
# let string_of_color = function | Blue -> "blue" | White -> "white" | Red -> "red";;
val string_of_color : color -> string = <fun>
# type point_3d = {x : float; y : float; z : float};;The simplest way to overcome this problem is simply ... to use different names! For instance
type point_3d = { x : float; y : float; z : float; } # type point_2d = {x : float; y : float};;
type point_2d = { x : float; y : float; } # {x = 10.; y = 20.; z = 30.};;
File "", line 1, characters 19-20: Error: The record field label z belongs to the type point_3d but is mixed here with labels of type point_2d
# type point3d = {x3d : float; y3d : float; z3d : float};;With OCaml, one can propose two others solutions. First, it is possible to use modules to define the two types in different name spaces:
type point3d = { x3d : float; y3d : float; z3d : float; } # type point2d = {x2d : float; y2d : float};;
type point2d = { x2d : float; y2d : float; }
# module D3 = struct type point = {x : float; y : float; z : float} end;;This way labels can be fully qualified as
module D3 : sig type point = { x : float; y : float; z : float; } end # module D2 = struct type point = {x : float; y : float} end;;
module D2 : sig type point = { x : float; y : float; } end
D3.x
D2.x:
# {D3.x = 10.; D3.y = 20.; D3.z = 30.};;You can also use objects that provide overloading on method names:
- : D3.point = {D3.x = 10.; D3.y = 20.; D3.z = 30.} # {D2.x = 10.; D2.y = 20.};;
- : D2.point = {D2.x = 10.; D2.y = 20.}
# class point_3d ~x ~y ~z = object method x : float = x method y : float = y method z : float = z end;;Note that objects provide you more than overloading: you can define truly polymorphic functions, working on both
class point_3d : x:float -> y:float -> z:float -> object method x : float method y : float method z : float end # class point_2d ~x ~y = object method x : float = x method y : float = y end;;
class point_2d : x:float -> y:float -> object method x : float method y : float end
point_3d and
point_2d, and you can even coerce a point_3d
to a point_2d.
# type ids = [ `Name | `Val ];;
type ids = [ `Name | `Val ] # type person = [ `Name of string ];;
type person = [ `Name of string ] # let f : person -> string = function `Name s -> s;;
val f : person -> string = <fun> # let is_name : ids -> bool = function `Name -> true | _ -> false;;
val is_name : ids -> bool = <fun>
let, followed by the name of the function and its
arguments; then the formula that computes the image of the argument is
written after an = sign.
# let successor (n) = n + 1;;In fact, parens surrounding the argument may be omitted, so we generally write:
val successor : int -> int = <fun>
# let successor n = n + 1;;
val successor : int -> int = <fun>
# let rec fact n = if n = 0 then 1 else n * fact (n - 1);;Functions may be mutually recursive:
val fact : int -> int = <fun> # let rec fib n = if n <= 1 then n else fib (n - 1) + fib (n - 2);;
val fib : int -> int = <fun>
# let rec odd n = if n = 0 then true else if n = 1 then false else even (n - 1) and even n = if n = 0 then false else if n = 1 then true else odd (n - 1);;
val odd : int -> bool = <fun> val even : int -> bool = <fun>
fib 2 instead of fib
(2), and fact x instead of fact
(x).f to -1 you must write
f (-1) and not f -1
that is syntactically similar to f - 1 (hence it is a
subtraction, not an application).
(). For instance, the
print_string primitive that prints a character string on
the terminal, just returns () as a way of
indicating that its job has been properly completed.() as dummy argument. For instance, the
print_newline procedure, that outputs a newline on the
terminal, gets no meaningful argument: it has type unit
-> unit.# let message s = print_string s; print_newline();;
val message : string -> unit = <fun> # message "Hello world!";;
Hello world! - : unit = ()
double_newline is bound to
(), and its further evaluation never
produces carriage returns as may be erroneously expected by the user.
# let double_newline = print_newline(); print_newline();;The correct definition and usage of this procedure is:
val double_newline : unit = () # double_newline;;
- : unit = ()
# let double_newline () = print_newline(); print_newline();;
val double_newline : unit -> unit = <fun> # double_newline;;
- : unit -> unit = <fun> # double_newline ();;
- : unit = ()
# let sum x y = x + y;;then gives the actual arguments in the same order when applying the function:
val sum : int -> int -> int = <fun>
# sum 1 2;;These functions are named “curried” functions, as opposed to functions with tuples as argument:
- : int = 3
# let sum' (x, y) = x + y;;
val sum' : int * int -> int = <fun> # sum' (1, 2);;
- : int = 3
# let div_mod x y = (x / y, x mod y);;
val div_mod : int -> int -> int * int = <fun> # div_mod 15 7;;
- : int * int = (2, 1)
fun, followed by
its argument, then an arrow -> and the function body.
For instance:
# fun x -> x + 1;;
- : int -> int = <fun> # (fun x -> x + 1) 2;;
- : int = 3
fun
and function?fun. Each parameter is introduced by its own
fun construct. For instance, the construct:
fun x -> fun y -> ...
defines a function with two parameters x and
y. An equivalent but shorter form is:
fun x y -> ...
Functions that use pattern-matching are
introduced by the keyword function.
For example:
function None -> false | Some _ -> true
print_newline without argument, there is
no error, but nothing happens. The compiler issues a warning in case
of a blatant misuse.
# print_newline;;
- : unit -> unit = <fun> # print_newline ();;
- : unit = ()
let f = function
| 0 -> match ... with | a -> ... | b -> ...
| 1 -> ...
| 2 -> ...
is parsed as
let f = function
| 0 ->
match ... with
| a -> ...
| b -> ...
| 1 -> ...
| 2 -> ...
This error may occur for every syntactic construct that involves
pattern matching: function, match
.. with
and try ... with. The usual trick is to
enclose inner pattern matchings with begin and
end. One write:
let f = function
| 0 ->
begin match ... with
| a -> ...
| b -> ...
end
| 1 -> ...
| 2 -> ...
# type t = T of int;;This phenomenon appears when you load many times the same file into the interactive system, since each reloading redefines the types. The solution is to quit your interactive system and reload your files in a new session.
type t = T of int # let x = T 1;;
val x : t = T 1 # type t = T of int;;
type t = T of int # let incr = function T x -> T (x+1);;
val incr : t -> t = <fun> # incr x;;
File "", line 1, characters 5-6: Error: This expression has type t/3264 but an expression was expected of type t/3267
function construct or an extra parameter (this
rewriting is known as eta-expansion):
# let map_id = List.map (function x -> x) (* Result is weakly polymorphic *);;The two definitions are semantically equivalent, and the new one can be assigned a polymorphic type scheme, since it is no more a function application.
val map_id : '_a list -> '_a list = <fun> # map_id [1;2];;
- : int list = [1; 2] # map_id (* No longer polymorphic *);;
- : int list -> int list = <fun> # let map_id' l = List.map (function x -> x) l;;
val map_id' : 'a list -> 'a list = <fun> # map_id' [1;2];;
- : int list = [1; 2] # map_id' (* Still fully polymorphic *);;
- : 'a list -> 'a list = <fun>
'_a); they will disappear
thanks to type inference as soon as enough informations will be given.
# let r = ref [];;Since the expression mentionned in the error message cannot be compiled as is, two cases must be envisioned:
val r : '_a list ref = {contents = []} # let f = List.map (fun x -> x);;
val f : '_a list -> '_a list = <fun>
r above. You must use an explicit
type annotation, in order to turn it into something completely
monomorphic.f.# let f (g : 'a -> 'a) x y = g x, g y;;The function is not as polymorphic as we could have hoped.
val f : ('a -> 'a) -> 'a -> 'a -> 'a * 'a = <fun>
# let f (o : < g : 'a. 'a -> 'a >) x y = o#g x, o#g y;;FIXME: A direct way now exists.
val f : < g : 'a. 'a -> 'a > -> 'b -> 'c -> 'b * 'c = <fun> # type id = { g : 'a. 'a -> 'a };;
type id = { g : 'a. 'a -> 'a; } # let f r x y = r.g x, r.g y;;
val f : id -> 'a -> 'b -> 'a * 'b = <fun>
format module, you might not mix printing commands from
format with printing commands from the basic I/O
system. In effect, the material printed by functions from the
format module is delayed (stored into the pretty-printing
queue) in order to find out the proper line breaking to perform with
the material at hand. By contrast low level output is performed with
no more buffering than usual I/O buffering.
# print_endline "before"; Format.print_string "MIDDLE"; print_endline "after";;To avoid this kind of problems you should not mix printing orders from
before after MIDDLE- : unit = ()
format and basic printing commands; that's the reason why
when using functions from the format module, it is
considered good programming habit to open format globally
in order to completely mask low level printing functions by the high
level printing functions provided by format.
module type S1 = sig ... type t ... end
module type S2 = sig ... type u ... end
To define a functor F that takes two arguments
X:S1 and Y:S2 such that X.t and
Y.u are the same, write:
module F (X: S1) (Y: S2 with type u = X.t) =
struct ... end
Indeed, internally this expands to
module F (X: S1) (Y: sig ... type u = X.t ... end) =
struct ... end
Set from the standard library.
quit();;.
With OCaml, type #quit;;. In both, you can also send an
end-of-file (CTRL-D for Unix, CTRL-Z for DOS, etc.).