CMSC330

Ocaml

OCaml

Typing
Functional Programming
Functions and Expressions
Lets
Lists and Pattern Matching
Data Types

Typing

Type Systems determine what data is and how it's used

Typing

Type Checking

Type Checking: The process of determining a variable's type

Dynamic typing: type checking is performed at run-time

Static typing: type checking is performed at compile-time

Typing

Manifest (explicit) typing: explicitly telling the compiler the type of new variables

Types are associated with variables

Latent (implicit) typing: not needing to give a type to a variable

Types are associated with values

Functional Programming

Functional Programming: a programming paradigm based on functions

Programming Paradigm: classification of programming approach based behaviour of code

Functional Programming

Programming Paradigm: classification of programming approach based behaviour of code

  • Typically used interchangibly with language features

  • Many languages have a ton of overap. eg:

  • Python is imperative, object-oriented, and functional

  • OCaml is imperative, object-oriented and functional

  • But they focus on different things!

Functional Programming

Features of functional languages

  • Immutable State

  • Declarative Programming

  • Referential transparency

Functional Programming

Program State: the state of the machine at any given time

Typically described as the contents of variables


# imperative.c
x = x + 1;
a[0] = 42;
          

Imperative: State is mutable, changing or destructive

Functional Programming

Imperative: State is mutable, changing or destructive

Can cause side effects (which is bad)


# side_effects.java
int count = 0;
int f(Node node){
  node.data = count;
  count+=1;
  return count;
}
          

No Referential transparency: replace expression with value with no side effects


f(x) + f(x) + f(x) != 3 * f(x) != 1 + 2 + 3
          

Functional Programming

Imperative: State is mutable, changing or destructive

Reality Check: No single state exists


# states.c
int x = 1;
if (fork() == 0)
  x = x + 1;
else
  x = x * 5;
wait(NULL)
printf("x: %d\n", x);
          

Functional Programming has immutable state

Functional Programming

Functional Programming uses immutable state

  • Will minimize side effects

  • Assumes referential transparency

  • Builds Correct Programs

Functional Programming

Declarative Programming


# imperative.py
def evens(arr):
  ret  = []
  for x in arr
    remainder = x % 2
    if remainder == 0:
      ret.append(x)
  return ret
          

as opposed to


declarative.py
def evens(arr):
  ret = [x for x in arr if x % 2 == 0]
  return ret
          

Functions and Expressions

Our First Ocaml Program


  (* hello.ml *)
  print_string "Hello World!\n"
            
  • No semi colon (for now)
  • (* *) for comment

OCaml is a compiled language


  ocamlc hello.ml
            
  • a.out: executable
  • hello.cmocompiled object (.o)
  • hello.cmicompiled interface (like .h)

Functions and Expressions

Helpful Programs

  • ocaml: repl like python
  • utop: like ocaml but better
  • dune like Make
  • opam package manager for OCaml

Probably want to run dune utop src

Will need to use ;; to end epxressions in utop

Functions and Expressions

Rememeber Syntax vs Semantics

Everything is an expression (e)

  • Expressions evaluate to values (v)
  • All values are expressions, but not vice versa
  • Expressions have types (t)
  • e: t will mean expression e has type t

Functions and Expressions


1 + 3
          

the expression 1+3 has type int


true
          

the value true has type bool

Expressions have types

Functions and Expressions

Expressions have types

The if expression


(if e1:bool then e2:t else e3:t):t
          

Actual Syntax:


if e1 then e2 else e3
          

Static and Latent Typing

Functions and Expressions

Expressions have types

functions are expressions


(* function.ml *)
let f x = 
  if x mod 2 = 0 then
    1
  else
    0
in f
;;
          

The expression f has type int->int

Type Inference: inferring a variable's type

Functions and Expressions


(* function.ml *)
let f x = 
  if x mod 2 = 0 then
    1
  else
    0
in f
;;
          

Function Definition Syntax

let f x1 ... xn = e

Function Calling Syntax

f x1 ... xn

Functions and Expressions

Function Calling Syntax

f x1 ... xn

Things that happen

  • Each argument x is evaluated to a value v
  • Substitute all x in e with v
  • Call the new expression e'
  • Evaluate e' to value v'

Functions and Expressions


(* factorial.ml *)
let rec f n = 
  if n = 0 then
    1
  else
    n * fact (n-1)
in f
;;
f 2;;
          

Type of f: int -> int

Type of f 2:int

Value of f 2: 2

Functions and Expressions

More on Type Checking

Types are inferred by operations they use


(* types.ml *)
(* compare two same types *)
1 = 1
x = y
x > y
x < y
(* x and y must have the same type *)

(* int have operators *)
3 + 4
x - y
x * y
x / y
x mod y

(* floats have different ones *)
3.2 +. 4.
x -. y
x *. y
x /. y

(* Strings have some too*)
"hello" ^ " world"

(* latent typing means inference *)
let f x y = if x > y then x else y-4;;
(* int -> int -> int *)
          

Let expressions


(* let.ml *)
let x = e1 in e2
          
  • Let expressions are not the same as let definitions
  • Bind local variables for e2
  • Scope is only for the body

Let expressions are expressions

Expressions have a type


(* let-type.ml *)
(let x = e1:t1 in e2:t2):t2
          

Let expressions

Let Expressions

Can be nested


(* let-nest.ml *)
let x = 3 in let y = 4 in x + y
          

Can be used for local variables


(* let-vars.ml *)
let area r = 
  let pi = 3.14 in
  pi *. r *. r
          

Variables will be shadowed


(* let-shadowing.ml *)
let x = 3 in let x = 5 in x + 4
          

Lists and Pattern Matching

Lists are the basic data structure in OCaml

  • Arbitrary Length
  • Homogenous
  • Implemented as a Linked List
  • Can be constructed and deconstructed

Lists and Pattern Matching

Lists are the basic data structure in OCaml


(* lists.ml *)
[1;2;3;4;5]
          
  • ; as seperator
  • Bracket Syntax
  • No indexing

List Creation


(* lists-1.ml *)
e1::e2::[]
          

Lists and Pattern Matching

Lists are the basic data structure in OCaml


(* lists-1.ml *)
e1::e2::[]
          
  • []- empty list (nil)
  • ::- cons
  • A list has a Head and Tail

Have type list

When evaluating, go right to left

Lists and Pattern Matching

Can deconstruct lists


(* match-nest.ml *)
let x = [1;2;3] in match x with
|[] -> true
|h::t -> false
          

Match looks at patterns of structure

Lists and Pattern Matching

Match looks at patterns of structure

Common Patterns


(* match-patterns.ml *)
let empty x = in match x with
|[] -> true (* empty *)
|a::[] -> false (* list of size 1 *)
|h::t -> false (* list at least size 1 *)
|_ -> false (* wildcard *)
          

Variables are bound on order

Last item is a list

Lists and Pattern Matching

Match looks at patterns of structure

Can be put as argument


(* match-function.ml *)
let car (h::_) = h;;
let cdr (_::t) = t;;
          

Lists and Pattern Matching

Match looks at patterns of structure

Can be Polymorphic


(* match-polymorphic.ml *)
let car lst = match lst with 
[] -> []
h::_ -> h;;
(* lst has type 'a list *)

let rec sum lst = match lst with
[]-> 0
|h::t -> h + sum t;;
(* h has type int list *)
          

Lists and Pattern Matching

Used commonly in recursive functions


(* match-rec-functions.ml *)
let rec sum lst = match lst with
[]-> 0
|h::t -> h + sum t;;

let rec negate lst = match lst with
[]-> []
|h::t -> -h + negate t;;

let rec last lst = match lst with
[x]-> x
|h::t -> last t;;

let rec append l m = match l with
[]-> m
|h::t -> x :: (append t m)

let rec rev l = match l with
|[] -> []
| h::t -> append (rev t) (h::[])
(* rev is O(n^2) *)
(* can you do better? *)
          

Data Types

Tuples

Like Lists, but not really


(* tuples.ml *)
(1,2)
          
  • Surrounded with ()
  • Seperated with ,
  • Heterogenous
  • Fixed size

Data Types

Tuples

Tuples have a set Type


(* tuples-type.ml *)
(1,2) (* int * int *)
(1,"string",2.3) (* int * string * float *)
('a','b') (* char * char *)
['a';'b'] (* char list *)
[(1,2);(3,4)] (* (int * int) list *)
([1;2],[3;4]) (* int list * int list *)
          

Data Types

Tuples

Can Pattern Match


(* tuples-match.ml *)
let add t = match t with
(a,b) -> a + b
          

Remember Tuples have a type based on size


(* tuples-match-err.ml *)
let add t = match t with
(a,b) -> a + b
|(a,b,c) -> a + b + c
          

Data Types

Records

Like a weird hash


(* records.ml *)
type data = { month: string; dat: int; year: int };;
let today = { day=29; year=2020; month="feb"};;
          

O in OCaml stands for Object


(* record-access-1.ml *)
print_string today.month
          

Can also pattern match


(* record-access-2.ml *)
let { month=_; day = d} = today in
print_int d
          

Data Types

User Defined Types

We just saw this syntax


(* ud-types-alias.ml *)
type ilist = int list;;
let f x:ilist = [1;2;3;4];;
          
  • Like a typedef
  • type keyword will allow for an alias

    Ultimately not really useful in this form

Data Types

Variant Types are more useful


(* ud-variants.ml *)
type parity = Even | Odd 
          

Like an enum


(* pm-variants.ml *)
let swap x = match x with
Even -> Odd
|Odd -> Even
          

    Can be Pattern Matched

Data Types

Can Hold Data


(* ud-variants-1.ml *)
type parity = Even of int | Odd of int
          

Can still be Pattern Matched


(* pm-variants-1.ml *)
let add x = match x with
Even(x) -> Odd(x+1)
|Odd(x) -> Even(x+1)
          

Data Types

Can Hold Data

Can be different


(* ud-variants-2.ml *)
type shape = Rect of int * int | Circle of float 
          

Can still be Pattern Matched


(* pm-variants-2.ml *)
let area s = match s with
Rect (w,l) -> float_of_int (w*l)
|Circle r  -> r *. r *. 3.14
          

Data Types

Can be Recursive


(* llist.ml *)
type linked = 
Item of string * linked
|Null;;

let head lst = match lst with
Item(x,_) -> x
|Null -> "";;

head (Item("Hello",Item("world", Null)));;
          

Data Types

Can be generic


(* some_none.ml *)
type 'a option = 
Some of 'a
|None
          

Built into OCaml