A pre-defined type in Standard ML is the type of truth values,
called bool. This has
exactly two values, true
and false. Another simple
type is string.
Strings are enclosed in double quotes (as in "Hello") and are
joined by ``^'' (the caret or up arrow symbol). As expected, the
expression "Hello" ^ " world!" evaluates to "Hello
world!". There also is a type char for single characters. A character constant is
a string constant of length one preceded by a hash symbol. Thus
#"a" is the letter a, #"\n" is the newline
character, #"\t"
is tab and the backslash character
can be used in the expected way to quote itself or the double quote
character. Eight-bit characters can be accessed by their ASCII code,
with #"\163"
yielding #"`£`",
#"\246"
yielding #"ö"
and so forth.
The function explode
turns a string into a list of single characters and implode goes the other
way. The function ord turns a character into its ASCII code and chr goes the other way.
The function size
returns the number of characters in a string. Because strings and
characters are values of different types we need a function to convert
a character into a string of length one. The function str is used for this.

The numeric types in Standard ML are the integers of type int, the real numbers of type real, and unsigned integers (or words) of type word. In addition to these, an implementation of the language may provide other numeric types in a library, for example perhaps arbitrary precision integers or double precision reals or even bytes (8-bit unsigned integers). The integers may be represented in decimal or hexadecimal notation thus 255 and 0xff (zero x ff) both represent the integer 255. The numbers have one striking oddity ``~'' (tilde) is used for unary minus (with the exception of words of course, which cannot be negative). Reals must have either a fraction part--as in 4000.0--or an exponent part--as in 4E3--or both. A word or byte constant is written as a decimal numeral if following the characters 0w (zero w) or as a hexadecimal numeral if following the characters 0wx (zero w x). Thus 0w255 and 0wxff are two different ways of writing the word constant 255. Integers, reals and words are thus lexically distinct and when we see a numeric constant we can infer its type, if we are not explicitly told what it is. Operators such as +, -, *, div and mod are provided for integers and words: +, -, * and / are provided for the reals. Functions such as absolute value, abs, and unary negation are provided for the signed numeric types only. Relational operators =, <>, <, <=, > and >= are provided for the numeric types.

The numeric types which we have mentioned are *separate types*
and we must use functions to convert an integer to a real or a word or
a byte. There is no implicit coercion between
types as found in other programming languages. Standard ML
provides two library functions to convert between integers and reals.
Arbitrary precision integer arithmetic is provided by some
implementations of the language. In order to determine which do and
which do not, consult the reference manual for the implementation or
calculate a large integer value, say by multiplying a million by
itself.

The integer successor function may be denoted by
**fn**
x =>
x+1.
Function application is indicated by juxtaposition of the
function--or function expression--and the argument value--or
argument expression. Parentheses are introduced where necessary. If
the argument to the function is to be obtained by evaluating an
expression then parentheses will be obligatory. They can be used at
other times just to clarify the structure of the function application.
As might be expected, the function application
(**fn** x =>
x+1) 4 evaluates to 5.
Function application associates to the left in Standard ML so an
expression which uses the successor function twice must use
parentheses, as in (**fn** x =>
x+1)
((**fn** x =>
x+1) 4). Since unary minus is a
function the parentheses are necessary in the expression ~
(~ x).

Of course, a mechanism is provided for binding names to values; even
titchy programs would be unreadable without it. The declaration
**val** succ =
**fn** x =>
x+1 binds the name
succ to the successor function and we may now write
succ (succ 4) as an abbreviation
for (**fn** x =>
x+1)
((**fn** x =>
x+1) 4).

Standard ML is a case-sensitive language . All of the reserved
words of the language, such as **val** and **fn**, must be in
lower case and occurrences of a program identifier must use
capitalization consistently.