Skip to content

19. Features for ML Compatibility

F# has its roots in the Caml family of programming languages and its core constructs are similar to some other ML-family languages. As a result, F# supports some constructs for compatibility with other implementations of ML-family languages.

19.1 Conditional Compilation for ML Compatibility

F# supports the following constructs for conditional compilation:

token start-fsharp-token = "(*IF-FSHARP" | "(*F#"
token end-fsharp-token = "ENDIF-FSHARP*)" | "F#*)"
token start-ml-token = "(*IF-OCAML*)"
token end-ml-token = "(*ENDIF-OCAML*)"

F# ignores the start-fsharp-token and end-fsharp-token tokens. This means that sections marked

(*IF-FSHARP ... ENDIF-FSHARP*)

or

(*F# ... F#*)

are included during tokenization when compiling with the F# compiler. The intervening text is tokenized and returned in the token stream as normal.

In addition, the start-ml-token token is discarded and the following text is tokenized as string , _ (any character), and end-ml-token until an end-ml-token is reached. Comments are not treated as special during this process and are simply processed as “other text”. This means that text surrounded by the following is excluded when compiling with the F# compiler:

(*IF-CAML*) ... (*ENDIF-CAML*)
or (*IF-OCAML*) ... (*ENDIF-OCAML*)

The intervening text is tokenized as “strings and other text” and the tokens are discarded until the corresponding end token is reached. Comments are not treated as special during this process and are simply processed as “other text.”

The converse holds when programs are compiled using a typical ML compiler.

19.2 Extra Syntactic Forms for ML Compatibility

The following identifiers are also keywords primarily because they are keywords in OCaml. Although F# reserves several OCaml keywords for future use, the /mlcompatibility option enables the use of these keywords as identifiers.

token ocaml-ident-keyword =
    asr land lor lsl lsr lxor mod

Note: In F# the following alternatives are available. The precedence of these operators differs from the precedence that OCaml uses.

asr >>> (on signed type)
land &&&
lor |||
lsl <<<
lsr >>> (on unsigned type)
lxor ^^^
mod %
sig begin (that is, begin/end may be used instead of sig/end)

F# includes the following additional syntactic forms for ML compatibility:

expr :=
    | ...
    | expr .( expr ) // array lookup
    | expr .( expr ) <- expr // array assignment
type :=
    | ...
    | ( type ,..., type ) long-ident // generic type instantiation

module-implementation :=
    | ...
    | module ident = struct ... end

module-signature :=
    | ...
    | module ident : sig ... end

An ML compatibility warning occurs when these constructs are used.

Note that the for-expression form for var = expr1 downto expr2 do expr3 is also permitted for ML compatibility.

The following expression forms

expr :=
    | ...
    | expr.(expr) // array lookup
    | expr.(expr) <- expr // array assignment

Are equivalent to the following uses of library-defined operators:

e1.(e2)               → (.()) e1 e2
e1.(e2) <- e3         → (.()<-) e1 e2 e3

19.3 Extra Operators

F# defines the following two additional shortcut operators:

e1 or e2                  → (or) e1 e2
e1 & e2                   → (&) e1 e2

19.4 File Extensions and Lexical Matters

F# supports the use of the .ml and .mli extensions on the command line. The “indentation awareness off” syntax option is implicitly enabled when using either of these filename extensions.

Lightweight syntax can be explicitly disabled in .fs, .fsi, .fsx, and .fsscript files by specifying #indent "off" as the first declaration in a file:

#indent "off"

When lightweight syntax is disabled, whitespace can include tab characters:

regexp whitespace = [ ' ' '\t' ]+