1 / 31

Objective Caml (Ocaml)

Objective Caml (Ocaml). Aaron Bloomfield CS 415 Fall 2005. ML history. ML first developed in late 1970’s Stands for Meta Langauage Not a “pure” function language Has functions with side effects, imperative programming capabilities Haskell is a pure functional language

stacia
Download Presentation

Objective Caml (Ocaml)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Objective Caml (Ocaml) Aaron Bloomfield CS 415 Fall 2005

  2. ML history • ML first developed in late 1970’s • Stands for Meta Langauage • Not a “pure” function language • Has functions with side effects, imperative programming capabilities • Haskell is a pure functional language • Uses Hindley-Milner type inference algorithm • Standard ML (SML) developed in 1990 • Most common version is njsml from Bell Labs • Caml developed in 1987 • Categorical Abstract Machine ML or CAML-ML or CAML • Ocaml came along in 1996 • Adds objects (which we won’t be using)

  3. Invoking Ocaml • From Cygwin: Aaron@Eridanus ~ $ ocaml Objective Caml version 3.08.1 # 5;; - : int = 5 # Ctrl-D Aaron@Eridanus ~ $ • Can install Ocaml on Linux as well

  4. Defining variables • All variables (and functions) are defined with the let command # let a = 5;; val a : int = 5 # let b = 5.5;; val b : float = 5.5 # let c = '5';; val c : char = '5' # let d = "5";; val d : string = "5" # • Ocaml automatically determines the type of the identifier from the definition • It does this for functions as well – more on this later

  5. Operators • The standard operators with the standard precedences • Note that: • * is integer multiplication • *. is floating point multiplication • Same for the other operators (/ + -) • Thus, 4.5 - 3.2 won’t work • Use 4.5 -. 3.2 • And Ocaml won’t allow you to mix types • You have to convert from one type to another yourself

  6. Lists • The main ‘workhorse’ in Ocaml # [1;2;3];; - : int list = [1; 2; 3] # let e = ["a";"b";"c"];; val e : string list = ["a"; "b"; "c"] # let f = [1,2,3];; val f : (int * int * int) list = [(1, 2, 3)] # let g = [1;'a';"b";2.0];; This expression has type char but is here used with type int # • You don’t have to declare a variable to declare a list • A comma separates parts of a tuple, not parts of a list • Lists must be homogenous – all parts of the same type

  7. ; vs , • ; separates elements of a list • , separates elements of a tuple # let g = [1;2;3];; val g : int list = [1; 2; 3] # let h = [1,2,3];; val h : (int * int * int) list = [(1, 2, 3)] # let i = [1,2;3,4];; val i : (int * int) list = [(1, 2); (3, 4)] # let j = [(1,2);(3,4)];; val j : (int * int) list = [(1, 2); (3, 4)] # • Parenthesis are just for human convenience

  8. List operators • List.hd • Calls the hd (head) function from the List module • Returns the first element of a list • Raises an exception on an empty list • List.tl • Returns the list without the head element • Raises an exception on an empty list • :: • Takes a head element and a list and glues them together • @ • Takes two lists and glues them together

  9. List operators • Examples # let l = [1;2;3];; val l : int list = [1; 2; 3] # List.hd l;; - : int = 1 # List.tl l;; - : int list = [2; 3] # 0 :: l;; - : int list = [0; 1; 2; 3] # [0] @ l;; - : int list = [0; 1; 2; 3] # • Note that :: takes an element and a list • Note that @ takes two lists

  10. More complex types • From the HW: let dfa1 = ("0", [("0", "0", "2"); ("0", "1", "1"); ("1", "0", "3"); ("1", "1", "0"); ("2", "0", "0"); ("2", "1", "3"); ("3", "0", "1"); ("3", "1", "2")], ["0"]);; • The type is: val dfa1 : string * (string * string * string) list * string list

  11. Defining functions # let f x = x+5;; val f : int -> int = <fun> # let g x = x+6;; val g : int -> int = <fun> # f 1;; - : int = 6 # f(1);; - : int = 6 # f(g(7));; - : int = 18 # • Ocaml automatically determines the type of the function • Called type inference

  12. Functions with multiple parameters • A function that takes two int parameters is different than a function that takes a int * int tuple as a parameter # let h x y = x+y;; val h : int -> int -> int = <fun> # let i x,y = x+y;; Syntax error # let i (x,y) = x+y;; val i : int * int -> int = <fun> # h 1;; - : int -> int = <fun> # let j = h 1;; val j : int -> int = <fun> # j 2;; - : int = 3 # • Note the required use of parenthesis when the parameter is a tuple • A function that takes two parameters can have just one passed to it • This then returns another function

  13. if … then syntax • Consider: # let x = 3;; val x : int = 3 # if x = 3 then 3;; This expression has type int but is here used with type unit # if x = 3 then 3 else 4;; - : int = 3 # • Note that parenthesis are not needed for the if condition • There must be an else clause

  14. A bad function let rec foo x = if ( x < 0 ) then 1 else 2.0;; • Ocaml’s type inference can’t determine the return type (int or float?)

  15. Defining recursive functions • Consider the Fibonacci function: # let fib n = if n=1 or n=2 then 1 else fib(n-1) + fib(n-2);; Unbound value fib • As fib has not been defined yet, Ocaml doesn’t know what the fib identifier means in the recursive call # let rec fib n = if n=1 or n=2 then 1 else fib(n-1) + fib(n-2);; val fib : int -> int = <fun> • All recursive functions in Ocaml need the rec keyword

  16. Binding issues • Consider: # let foo x = x+5;; val foo : int -> int = <fun> # let bar = foo;; val bar : int -> int = <fun> # let foo x = x+6;; val foo : int -> int = <fun> # foo 1;; - : int = 7 # bar 1;; - : int = 6 # • Note that although foo has been redefined, bar still uses the old foo

  17. Mutually recursive functions • When two functions call each other recursively let rec even x = if x = 0 then true else odd (x-1) and odd x = if x = 0 then false else even (x-1);; • I needed mutually recursive functions for the nfasimulate function

  18. let … in syntax • Allows you to declare local values: let fun foo x = let y = 5 in let z = square x in x*y*z;; • Can nest them as many as desired • Can also declare local functions this way: let quad x = let square x = x * x in (square x) * (square x);;

  19. match keyword • Allows you to do both case statements and breaking apart of complex data types let rec countlist list = match list with [] -> 0 | _ :: tail -> 1 + (countlist tail);; • The ‘_’ is used when you want to match something, but don’t plan on using it in the match

  20. The match keyword, continued • Consider the transitions part of the FAs • Type is (string * string * string) list let fun foo trans = match trans with [] -> ... | (a, b, “a”) :: tail -> ... | (a, b, c) :: tail -> ... • Most of my functions used the match keyword to break apart the parts of the FA parameter

  21. User defined types • User can define custom types type btree = Node of int * btree * btree | Leaf;; let mytree = Node (1, Node(2, Leaf, Leaf), Leaf);; let rec countnodes tree = match tree with Leaf -> 0 | Node (_, lefttree, righttree) -> 1 + (countnodes lefttree) + (countnodes righttree);; • Type name (here ‘btree’) must be all lower case

  22. More on user defined types • If you want a function to return a float or an int or a string: # type multi = Int of int | Float of float | String of string;; type multi = Int of int | Float of float | String of string # Int(7);; - : multi = Int 7 # Float(3.4);; - : multi = Float 3.4 # String "st";; - : multi = String "st" # let foo x = if x = 0 then Int 0 else if x < 0 then Float 0.0 else String "0";; val foo : int -> multi = <fun> #

  23. The #use command • To read in a file into Ocaml use #use: # #use "fa.ml";; • This will read in (and evaluate) the file fa.ml • You can then use the functions in the interpreter • This is probably the only ‘function’ with side-effects that you’ll be using

  24. Generics • Consider: # let rec countlist list = match list with [] -> 0 | _ :: tail -> 1 + (countlist tail);; val countlist : 'a list -> int = <fun> # • This function works on any type of list • the ‘a (read as alpha) means that any type can be substituted for alpha • Including (string list * char) list, for example • The List.hd function has type ‘a list -> ‘a • Meaning the type returned is the type of list read in

  25. Using modules • For the homework, you are allowed to use any functions in the List or String modules • You can refer to them as List.hd, List.tl, etc. • If you do anopen List;;you can then refer to them just as hd or tl • Note if you open the String module, it defines a new compare method • Which will cause issues if you are using ‘sort compare’ from the List module (see next slide)

  26. List module functions • map • Applies the passed function to each element in the list • Usage: map square [1;2;3;4];; • Result: [1;4;9;16] • sort • Allows you to sort elements in a list • First parameter must be the comparitor • The function that tells how to order individual elements • Use ‘compare’ for this • Note that if you open the String module, there is a different compare function, which will prevent the following from working • Usage: sort compare [4;3;2;1];; • Etc. • See the module documentation for more List module functions

  27. Debugging Ocaml functions • So how to debug the functions? • You can’t really use print statements • There is an ocaml debugger • Called ocamldebug • Installs with the Cygwin ocaml package • Build in little steps • And test each step to make sure it works • Make sure the types of your functions match what you expect them to be • Do a lot of hand-tracing • It’s a pain, but it will find your bug • You can use the interpreter for this…

  28. Ocaml gotchas • Using ;; to terminate functions (not a single ;) • ; vs , for lists vs tuples • #use “fa.ml”;; to read in a file • (* Comments are enclosed in star-parenthesis *) • The difference between :: and @ • String.compare overwriting the default compare • + vs +. (and similar for * / -)

  29. Function example: uniq • This method takes in a sorted list, and removes any duplicates • As the list is sorted, any duplicates would be next to each other • Name is short-hand for unique • Operates like the Un*x command of the same name let rec uniq list = match list with [] -> [] | h1 :: [] -> h1 :: [] | h1 :: h2 :: tail -> if h1 = h2 then uniq (h2 :: tail) else h1 :: uniq (h2 :: tail);;

  30. NFA to DFA conversion

  31. Homework hints • For the NFA to DFA conversion • When dealing with the DFA states, I found it easier to have the state names be sets (lists) for the intermediate functions • Use uniq and List.sort to ensure that the sets (lists) are equivalent • You will have to write intermediate steps for each part of the conversion algorithm

More Related