Fan favorites
let succ ?x:(y : int = 0) () = y + 1
let foo : type a. a My_gadt.t -> unit = fun x -> ignore x
type t = { f : 'a. 'a list -> int }
Mutually recursive modules
module rec Foo : sig
type t = Bar of Bar.t | Nil
end and Bar : sig
type t = Foo of Foo.t | Nil
end
module rec Foo : sig
type t = Bar of Bar.t | Nil
end = struct
type t = Bar of Bar.t | Nil
end and Bar : sig
type t = Foo of Foo.t | Nil
end = struct
type t = Foo of Foo.t | Nil
end
Recursive module definitions always require explicit signatures.
For loop
let sum = ref 0 in
for i = 1 to 3 do
sum := !sum + i
done;
assert (!sum = 6)
Note that the range is inclusive on both ends.
Universally quantified record field
type t = { f : 'a. 'a list -> int }
type t = { f : 'a. 'a list -> int }
First-Class Modules
First-class module parameter (module-style)
val min : (module Comparable.S with type t = 'a) -> 'a -> 'a -> 'a
let min (type a)
(module Compare : Comparable.S with type t = a)
(x : a) (y : a) =
if Compare.( < ) x y then x else y
Named first-class module parameter (module-style)
val min : compare:(module Comparable.S with type t = 'a) -> 'a -> 'a -> 'a
let min (type a)
~compare:(module Compare : Comparable.S with type t = a)
(x : a) (y : a) =
if Compare.( < ) x y then x else y
As far as I can tell there is no way to express an optional parameter in this way, even if you provide a default.
First-class module parameter (value-style)
val min : (module Comparable.S with type t = 'a) -> 'a -> 'a -> 'a
let min (type a)
(compare : (module Comparable.S with type t = a))
(x : a) (y : a) =
let module Compare = (val compare) in
if Compare.( < ) x y then x else y
Named first-class module parameter (value-style)
val min : compare:(module Comparable.S with type t = 'a) -> 'a -> 'a -> 'a
let min (type a)
~(compare : (module Comparable.S with type t = a))
(x : a) (y : a) =
let module Compare = (val compare) in
if Compare.( < ) x y then x else y
Named optional first-class module parameter with default (value-style)
val min : ?compare:(module Comparable.S with type t = 'a) -> 'a -> 'a -> 'a
let min (type a)
?(compare : (module Comparable.S with type t = a) = (module struct
type t = a
let (<) _ _ = false
(* etc *)
end))
(x : a) (y : a) =
let module Compare = (val compare) in
if Compare.( < ) x y then x else y
The inline module is only necessary if you need to refer to type variables from the signature. For simpler module types, you can provide a named module as the default with ?(m : S = (module M))
.
First-class module argument
min (module Int) 1 2
Function Signatures
Annotated return type
val succ : int -> int
let succ x : int = x + 1
Annotated positional argument
val succ : int -> int
let succ (x : int) = x + 1
Annotated return type and positional argument
val succ : int -> int
let succ (x : int) : int = x + 1
Named argument
val succ : x:int -> int
let succ ~x = x + 1
Renamed argument
val succ : x:int -> int
let succ ~x:y = y + 1
Named argument with annotated return type
val succ : x:int -> int
let succ ~x : int = x + 1
Note that the space between the identifier and the colon is significant to disambiguate this from a renamed argument.
Renamed argument with annotated return type
val succ : x:int -> int
let succ ~x:y : int = y + 1
The space between the identifier and the second colon is no longer required, as there is no more ambiguity.
Annotated named argument
val succ : x:int -> int
let succ ~(x : int) = x + 1
Annotated renamed argument
val succ : x:int -> int
let succ ~x:(y : int) = y + 1
Optional argument
val succ : ?x:int -> unit -> int option
let succ ?x () = Option.map ~f:(fun n -> n + 1) x
Note that optional arguments without subsequent positional arguments will generate a compiler warning, so we add a final unit argument to get around that. See here for more information.
Optional argument with a default value
val succ : ?x:int -> unit -> int
let succ ?(x = 0) () = x + 1
Annotated optional argument
val succ : ?x:int -> unit -> int option
let succ ?(x : int option) () = Option.map ~f:(fun n -> n + 1) x
Annotated optional argument with a default value
val succ : ?x:int -> unit -> int
let succ ?(x : int = 0) () = x + 1
Renamed annotated optional argument with a default value
val succ : ?x:int -> unit -> int
let succ ?x:(y : int = 0) () = y + 1
Explicit passing of an optional argument
let succ ?(x : int = 0) () = x + 1
let one = succ ?x:None ()
let two = succ ?x:(Some one) ()
let negative_succ ?(x : int option) () = -(succ ?x ())
Locally abstract type (monomorphic)
val foo : 'a My_gadt.t -> unit
let foo (type a) (x : a My_gadt.t) = ignore x
You will often see type variables introduced like this so that a GADT’s phantom can vary over different branches of a match statement. See here for more information.
Locally abstract type (polymorphic)
val foo : 'a My_gadt.t -> unit
let foo : type a. a My_gadt.t -> unit =
fun x -> ignore x
This is useful when you have a recursive GADT where the components of a value have a different phantom type than the value itself. See here for more information.