A Functional Programming Language: ML

A Programming Language is:

  1. a language for a virtual compuation environment
  2. a very formal language
  3. precise syntax (structure)
    1. Which symbols can be used, and how can they be composed
  4. precise semantics (meaning)
    1. What do the symbols mean

ML:

  1. a functional programming language (i.e., based on math. functions)
  2. designed by Robin Milner

ML Expressions -- Composition of values and operators, ended with a semicolon

ML evaluates the expression given, and prints the result

  1. the result has a name - it
  2. the result has a value - 7
  3. the result has a type - int

Type is a very important and fundamental concept

  1. defines a set of values that can be used
  2. expressions must have type consistency
  3. so, integers, reals, booleans, and strings are the fundamental types in ML


ML has Constants of five types:

  1. Integers -- a string of digits (0-9), optionally preceded by a tilde (~) to indicate negative
    1. Do we really need to say what an integer is? Yes.
  2. Reals -- string of digits (possibly preceded by ~), followed by at least one of
    1. a decimal point and one or more digits
    2. the letter E, followed by an integer
  3. Booleans -- true or false
  4. Characters -- Ascii characters, e.g., #"A"
  5. Strings -- a sequence of characters enclosed with double-quotes (")
    1. \ is a special character, and means that the next character (or more) indicate something special
    2. \n is the newline character, basically just like hitting the Return key
    3. \t is the tab character -- like hitting the Tab key
    4. \\ is the backslash -- since one \ is special, just type \\ to really mean backslash
    5. \" is the double-quote -- a plain double-quote would mean the end of the string, to have a double-quote actually be in the string, you use \"
    6. \### is a way to specify a character by its ASCII number
    7. \^A for any letter A is a way to specify a control character
    8. \ as the last character on the line means the string continues on the following line


Arithmetic operators: +,-,*,/,div,mod,~

Question: What order of evaluation?

Answer: operators have precedence relations

  1. negation (unary minus) is evaluated first (highest precendence)
  2. multiplication operators are next
  3. addition operators are last
  4. parentheses, of course, override these rules (technically, they have highest precedence)

Question: When are spaces needed?

Answer: when ML can't figure it out itself

String operators: 

  1. ^ is concatenation; that is, it makes one string out of two by slapping them together, end to end
  2. "" is an empty string, and is allowed

Comparison (Relational) Operators: =, <, >, <=, >=, <>

  1. These can compare two values of the same type: integer, real, or string
  2. The result is a value of type Boolean (true or false)
  3. They have lower precedence than any arithmetic operators (i.e., evaluate after)

Logical Operators: andalso, orelse, not

  1. They can only operate on Boolean values, and result in Boolean values
  2. Even lower precedence than Comparison operators, and orelse is lower than andalso
  3. orelse is an inclusive or, as opposed to an exclusive or
  4. Truthtables of each (done in class)

If-then-else Operator

  1. An operator? Yes, it takes operands and evaluates to a result
  2. The form is if expr1 then expr2 else expr3
  3. expr1 must result in a Boolean value
  4. expr2 and expr3 must result in values of the same type
  5. the result of the if-then-else operator is the value of expr2 if expr1 is true, otherwise it is the value of expr3; the type of the result is the type of expr2 and expr3

some examples found here

Type consistency

  1. ML is a strongly typed language
  2. Every operator (and function) has a specific type signature, and this cannot be violated.
  3. For example, the operator ^ (which concatenates two strings) has a type signature of string*string->string
    1. reads as "takes a string and another string, and results in a string".
    2. order is important for the *
  4. What about +? We used it with both integers and reals. What is its type signature?
    1. it has two: int*int->int and real*real->real
    2. but not int*real or real*int!
    3. we say that + is an overloaded operator, because it has more than one signature
  5. Resulting types do not have to be the same as the argument types. The type signatures of the overloaded relational operator > are:
    1. int*int->bool
    2. real*real->bool
    3. string*string->bool
  6. The type signature of the if-then-else operator is bool*t*t->t where t is some type.

Type conversion (coercion)

  1. Values can be converted between types
  2. Think of the coercion as a function taking one argument of a type, and returning a value of another type.
  3. Easiest: integer to real: real(3) is 3.0
  4. What about real to integer: depends on how you want it:
    1. floor, ceil (ceiling), trunc (truncate)
  5. character to integer? integer to character?
  6. string to integer? real to string?

Identifiers

  1. The val statement associates an identifier with a value (which can be computed from an expression)
  2. The value still has a specific type, even when referenced through the identifier
  3. val pi = 3.14156; means that the identifier pi refers to the real value 3.14156
  4. The identifier can be used in an expression, or in general any place a value of that type can be used
  5. Type consistency is still maintained
  6. Identifiers are not declared ahead of time to hold specific types; they are simply assigned typed values.

Some more examples here