diff --git a/ocaml.html.markdown b/ocaml.html.markdown index fcd12951..2c5e13d5 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -4,8 +4,8 @@ filename: learnocaml.ml contributors: - ["Daniil Baturin", "http://baturin.org/"] - ["Stanislav Modrak", "https://stanislav.gq/"] + - ["Luke Tong", "https://lukert.me/"] --- - OCaml is a strictly evaluated functional language with some imperative features. @@ -17,6 +17,8 @@ used interactively, and a compiler. The interpreter binary is normally called `ocaml` and the compiler is `ocamlopt`. There is also a bytecode compiler, `ocamlc`, but there are few reasons to use it. +It also includes a package manager, `opam`, and a build system, `dune`. + It is strongly and statically typed, but instead of using manually written type annotations, it infers types of expressions using the [Hindley-Milner](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system) @@ -58,7 +60,6 @@ The `f(x,y) = x + y` function from the example above applied to arguments 2 and 3 is equivalent to the `f0(y) = 2 + y` function applied to 3. Hence the `int -> int -> int` signature. - ```ocaml (*** Comments ***) @@ -76,6 +77,7 @@ Hence the `int -> int -> int` signature. is often considered to be a bad style. *) (* Variable and function declarations use the "let" keyword. *) +(* Variables are immutable by default in OCaml *) let x = 10 ;; (* OCaml allows single quote characters in identifiers. @@ -227,6 +229,10 @@ List.filter (fun x -> x mod 2 = 0) [1; 2; 3; 4] ;; often referred to as "cons". *) 1 :: [2; 3] ;; (* Gives [1; 2; 3] *) +(* Remember that the cons :: constructor can only cons a single item to the front + of a list. To combine two lists use the append @ operator *) +[1; 2] @ [3; 4] ;; (* Gives [1; 2; 3; 4] *) + (* Arrays are enclosed in [| |] *) let my_array = [| 1; 2; 3 |] ;; @@ -295,11 +301,55 @@ let my_point = Point (2.0, 3.0) ;; type 'a list_of_lists = 'a list list ;; type int_list_list = int list_of_lists ;; +(* These features allow for useful optional types *) +type 'a option = Some of 'a | None ;; +let x = Some x ;; +let y = None ;; + (* Types can also be recursive. Like in this type analogous to a built-in list of integers. *) type my_int_list = EmptyList | IntList of int * my_int_list ;; let l = IntList (1, EmptyList) ;; +(* or Trees *) +type 'a tree = + | Empty + | Node of 'a tree * 'a * 'a tree + +let example_tree: int tree = + Node ( + Node (Empty, 7, Empty), + 5, + Node (Empty, 9, Empty) + ) +(* + 5 + / \ + 7 9 +*) + +(*** Records ***) + +(* A collection of values with named fields *) + +type animal = + { + name: string; + color: string; + legs: int; + } +;; + +let cow = + { name: "cow"; + color: "black and white"; + legs: 4; + } +;; +val cow : animal + +cow.name ;; +- : string = "cow" (*** Pattern matching ***) @@ -346,6 +396,19 @@ let say x = say (Cat "Fluffy") ;; (* "Fluffy says meow". *) +(* However, pattern matching must be exhaustive *) +type color = Red | Blue | Green ;; +let what_color x = + match x with + | Red -> "color is red" + | Blue -> "color is blue" + (* Won't compile! You have to add a _ case or a Green case + to ensure all possibilities are accounted for *) +;; +(* Also, the match statement checks each case in order. + So, if a _ case appears first, none of the + following cases will be reached! *) + (** Traversing data structures with pattern matching **) (* Recursive types can be traversed with pattern matching easily. @@ -372,13 +435,76 @@ let rec sum_int_list l = let t = Cons (1, Cons (2, Cons (3, Nil))) ;; sum_int_list t ;; + +(* Heres a function to tell if a list is sorted *) +let rec is_sorted l = + match l with + | x :: y :: tail -> x <= y && is_sorted (y :: tail) + | _ -> true +;; + +is_sorted [1; 2; 3] ;; (* True *) +(* OCaml's powerful type inference guesses that l is of type int list + since the <= operator is used on elements of l *) + +(* And another to reverse a list *) +let rec rev (l: 'a list) : 'a list = + match l with + | [] -> [] + | x::tl -> (rev tl) @ [x] +;; + +rev [1; 2; 3] ;; (* Gives [3; 2; 1] *) +(* This function works on lists of any element type *) + +(*** Higher Order Functions ***) + +(* Functions are first class in OCaml *) + +let rec transform (f: 'a -> 'b) (l: 'a list) : 'b list = + match l with + | [] -> [] + | head :: tail -> (f head) :: transform f tail +;; + +transform (fun x -> x + 1) [1; 2; 3] ;; (* Gives [2; 3; 4] *) + +(** Lets combine everything we learned! **) +let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list = + begin match l with + | [] -> [] + | x :: xs -> + let rest = filter pred xs in + if pred x then x :: rest else rest + end +;; + +filter (fun x -> x < 4) [3; 1; 4; 1; 5] ;; (* Gives [3; 1; 1]) *) + +(*** Mutability ***) + +(* Records and variables are immutable: you cannot change where a variable points to *) + +(* However, you can create mutable polymorphic fields *) +type counter = { mutable num : int } ;; + +let c = { num: 0 } ;; +c.num ;; (* Gives 0 *) +c.num <- 1 ;; (* <- operator can set mutable record fields *) +c.num ;; (* Gives 1 *) + +(* OCaml's standard library provides a ref type to make single field mutability easier *) +type 'a ref = { mutable contents : 'a } ;; +let counter = ref 0 ;; +!counter ;; (* ! operator returns x.contents *) +counter := !counter + 1 ;; (* := can be used to set contents *) ``` ## Further reading -* Visit the official website to get the compiler and read the docs: -* Quick tutorial on OCaml: -* Complete online OCaml v5 playground: -* An up-to-date (2022) book (with free online version) "Real World OCaml": -* Online interactive textbook "OCaml Programming: Correct + Efficient + Beautiful" from Cornell University: -* Try interactive tutorials and a web-based interpreter by OCaml Pro: +* Visit the official website to get the compiler and read the docs: [http://ocaml.org/](http://ocaml.org/) +* Quick tutorial on OCaml: [https://ocaml.org/docs/up-and-running](https://ocaml.org/docs/up-and-running) +* Complete online OCaml v5 playground: [https://ocaml.org/play](https://ocaml.org/play) +* An up-to-date (2022) book (with free online version) "Real World OCaml": [https://www.cambridge.org/core/books/real-world-ocaml-functional-programming-for-the-masses/052E4BCCB09D56A0FE875DD81B1ED571](https://www.cambridge.org/core/books/real-world-ocaml-functional-programming-for-the-masses/052E4BCCB09D56A0FE875DD81B1ED571) +* Online interactive textbook "OCaml Programming: Correct + Efficient + Beautiful" from Cornell University: [https://cs3110.github.io/textbook/cover.html](https://cs3110.github.io/textbook/cover.html) +* Try interactive tutorials and a web-based interpreter by OCaml Pro: [http://try.ocamlpro.com/](http://try.ocamlpro.com/)