ML Lecture 2

Review: Operators

Review: Types

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
  6. Think about disjoint functions in math

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->(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)
    2. floor moves left on the number line
    3. ceil moves right
    4. trunc moves towards 0
    5. note that none of these does rounding
  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. Note: unlike other languages you may have used, identifiers are not declared ahead of time to hold specific types; they are simply assigned typed values.

Examples on slides are found here