├── .gitignore ├── ocaml ├── chapter-01.ml ├── chapter-03.ml ├── chapter-04.ml ├── chapter-02.ml ├── chapter-09.ml ├── chapter-07.ml ├── chapter-05.ml ├── chapter-08.ml ├── chapter-06.ml └── chapter-10.ml ├── reasonbs ├── chapter01.re ├── chapter03.re ├── chapter04.re ├── chapter02.re ├── chapter07.re ├── chapter09.re ├── chapter05.re ├── chapter06.re ├── chapter08.re └── chapter10.re ├── reasonml ├── chapter-01.re ├── chapter-03.re ├── chapter-04.re ├── chapter-02.re ├── chapter-07.re ├── chapter-09.re ├── chapter-05.re ├── chapter-06.re ├── chapter-08.re └── chapter-10.re ├── bsconfig.json ├── package.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/.lsp/debug.log 2 | 3 | .DS_Store 4 | .merlin 5 | .bsb.lock 6 | npm-debug.log 7 | lib/bs/ 8 | /node_modules/ 9 | *.bs.js -------------------------------------------------------------------------------- /ocaml/chapter-01.ml: -------------------------------------------------------------------------------- 1 | (* 16 *) 2 | type seasoning = 3 | Salt 4 | | Pepper 5 | 6 | (* 21 *) 7 | type num = 8 | Zero 9 | | One_more_than of num 10 | 11 | (* 32 *) 12 | type 'a open_faced_sandwich = 13 | Bread of 'a 14 | | Slice of 'a open_faced_sandwich 15 | -------------------------------------------------------------------------------- /reasonbs/chapter01.re: -------------------------------------------------------------------------------- 1 | /* 16 */ 2 | type seasoning = 3 | | Salt 4 | | Pepper; 5 | 6 | /* 21 */ 7 | type num = 8 | | Zero 9 | | One_more_than(num); 10 | 11 | /* 32 */ 12 | type open_faced_sandwich('a) = 13 | | Bread('a) 14 | | Slice(open_faced_sandwich('a)); 15 | -------------------------------------------------------------------------------- /reasonml/chapter-01.re: -------------------------------------------------------------------------------- 1 | /* 16 */ 2 | type seasoning = 3 | | Salt 4 | | Pepper; 5 | 6 | /* 21 */ 7 | type num = 8 | | Zero 9 | | One_more_than(num); 10 | 11 | /* 32 */ 12 | type open_faced_sandwich('a) = 13 | | Bread('a) 14 | | Slice(open_faced_sandwich('a)); 15 | -------------------------------------------------------------------------------- /bsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "the-little-ocamler", 3 | "version": "0.1.0", 4 | "sources": { 5 | "dir" : "reasonbs", 6 | "subdirs" : true 7 | }, 8 | "package-specs": { 9 | "module": "commonjs", 10 | "in-source": true 11 | }, 12 | "suffix": ".bs.js", 13 | "bs-dependencies": [ 14 | 15 | ], 16 | "warnings": { 17 | "error" : "+101" 18 | }, 19 | "namespace": true, 20 | "refmt": 3 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "the-little-ocamler", 3 | "version": "1.0.0", 4 | "description": "the little ocamler code from book", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "bsb -make-world -w", 8 | "build": "bsb -make-world", 9 | "clean": "bsb -clean-world", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "license": "MIT", 13 | "devDependencies": { 14 | "bs-platform": "^7.3.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ocaml/chapter-03.ml: -------------------------------------------------------------------------------- 1 | (* 1 *) 2 | type pizza = 3 | Crust 4 | | Cheese of pizza 5 | | Onion of pizza 6 | | Anchovy of pizza 7 | | Sausage of pizza 8 | 9 | (* 31 *) 10 | let rec remove_anchovy = 11 | function 12 | Crust -> Crust 13 | | Cheese x -> Cheese (remove_anchovy x) 14 | | Onion x -> Onion (remove_anchovy x) 15 | | Anchovy x -> remove_anchovy x 16 | | Sausage x -> Sausage (remove_anchovy x) 17 | 18 | (* 43 *) 19 | let rec top_anchovy_with_cheese = 20 | function 21 | Crust -> Crust 22 | | Cheese x -> Cheese (top_anchovy_with_cheese x) 23 | | Onion x -> Onion (top_anchovy_with_cheese x) 24 | | Anchovy x -> Cheese (Anchovy (top_anchovy_with_cheese x)) 25 | | Sausage x -> Sausage (top_anchovy_with_cheese x) 26 | 27 | (* 49 *) 28 | let subst_anchovy_by_cheese x = 29 | remove_anchovy (top_anchovy_with_cheese x) 30 | 31 | (* 53 *) 32 | let rec subst_anchovy_by_cheese = 33 | function 34 | Crust -> Crust 35 | | Cheese x -> Cheese (subst_anchovy_by_cheese x) 36 | | Onion x -> Onion (subst_anchovy_by_cheese x) 37 | | Anchovy x -> Cheese (subst_anchovy_by_cheese x) 38 | | Sausage x -> Sausage (subst_anchovy_by_cheese x) 39 | -------------------------------------------------------------------------------- /ocaml/chapter-04.ml: -------------------------------------------------------------------------------- 1 | (* 4 *) 2 | type meza = Shrimp | Calamari | Escargots | Hummus 3 | 4 | (* 5 *) 5 | type main = Steak | Ravioli | Chicken | Eggplant 6 | 7 | type salad = Green | Cucumber | Greek 8 | 9 | (* 6 *) 10 | type dessert = Sundae | Mousse | Torte 11 | 12 | (* 25 *) 13 | let add_a_steak = 14 | function 15 | Shrimp -> (Shrimp, Steak) 16 | | Calamari -> (Calamari, Steak) 17 | | Escargots -> (Escargots, Steak) 18 | | Hummus -> (Hummus, Steak) 19 | 20 | (* 42 *) 21 | (* No way I'm typing all that *) 22 | 23 | (* 46 *) 24 | let eq_main = 25 | function 26 | Steak, Steak -> true 27 | | Ravioli, Ravioli -> true 28 | | Chicken, Chicken -> true 29 | | Eggplant, Eggplant -> true 30 | | a_main, another_main -> false 31 | 32 | (* 54 *) 33 | let has_steak = 34 | function 35 | meza, Steak, dessert -> true 36 | | meza, main, dessert -> false 37 | 38 | (* 66 *) 39 | let has_steak : meza * main * dessert -> bool = 40 | function 41 | a, Steak, d -> true 42 | | a, ns, d -> false 43 | 44 | (* 67 *) 45 | let add_a_steak : meza -> meza * main = 46 | fun x -> x, Steak 47 | (* Shorter: *) 48 | let add_a_steak (x : meza) = x, Steak 49 | -------------------------------------------------------------------------------- /reasonbs/chapter03.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type pizza = 3 | | Crust 4 | | Cheese(pizza) 5 | | Onion(pizza) 6 | | Anchovy(pizza) 7 | | Sausage(pizza); 8 | 9 | /* 31 */ 10 | let rec remove_anchovy = 11 | fun 12 | | Crust => Crust 13 | | Cheese(x) => Cheese(remove_anchovy(x)) 14 | | Onion(x) => Onion(remove_anchovy(x)) 15 | | Anchovy(x) => remove_anchovy(x) 16 | | Sausage(x) => Sausage(remove_anchovy(x)); 17 | 18 | /* 43 */ 19 | let rec top_anchovy_with_cheese = 20 | fun 21 | | Crust => Crust 22 | | Cheese(x) => Cheese(top_anchovy_with_cheese(x)) 23 | | Onion(x) => Onion(top_anchovy_with_cheese(x)) 24 | | Anchovy(x) => Cheese(Anchovy(top_anchovy_with_cheese(x))) 25 | | Sausage(x) => Sausage(top_anchovy_with_cheese(x)); 26 | 27 | /* 49 */ 28 | let subst_anchovy_by_cheese = x => 29 | remove_anchovy(top_anchovy_with_cheese(x)); 30 | 31 | /* 53 */ 32 | let rec subst_anchovy_by_cheese = 33 | fun 34 | | Crust => Crust 35 | | Cheese(x) => Cheese(subst_anchovy_by_cheese(x)) 36 | | Onion(x) => Onion(subst_anchovy_by_cheese(x)) 37 | | Anchovy(x) => Cheese(subst_anchovy_by_cheese(x)) 38 | | Sausage(x) => Sausage(subst_anchovy_by_cheese(x)); 39 | -------------------------------------------------------------------------------- /reasonml/chapter-03.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type pizza = 3 | | Crust 4 | | Cheese(pizza) 5 | | Onion(pizza) 6 | | Anchovy(pizza) 7 | | Sausage(pizza); 8 | 9 | /* 31 */ 10 | let rec remove_anchovy = 11 | fun 12 | | Crust => Crust 13 | | Cheese(x) => Cheese(remove_anchovy(x)) 14 | | Onion(x) => Onion(remove_anchovy(x)) 15 | | Anchovy(x) => remove_anchovy(x) 16 | | Sausage(x) => Sausage(remove_anchovy(x)); 17 | 18 | /* 43 */ 19 | let rec top_anchovy_with_cheese = 20 | fun 21 | | Crust => Crust 22 | | Cheese(x) => Cheese(top_anchovy_with_cheese(x)) 23 | | Onion(x) => Onion(top_anchovy_with_cheese(x)) 24 | | Anchovy(x) => Cheese(Anchovy(top_anchovy_with_cheese(x))) 25 | | Sausage(x) => Sausage(top_anchovy_with_cheese(x)); 26 | 27 | /* 49 */ 28 | let subst_anchovy_by_cheese = x => 29 | remove_anchovy(top_anchovy_with_cheese(x)); 30 | 31 | /* 53 */ 32 | let rec subst_anchovy_by_cheese = 33 | fun 34 | | Crust => Crust 35 | | Cheese(x) => Cheese(subst_anchovy_by_cheese(x)) 36 | | Onion(x) => Onion(subst_anchovy_by_cheese(x)) 37 | | Anchovy(x) => Cheese(subst_anchovy_by_cheese(x)) 38 | | Sausage(x) => Sausage(subst_anchovy_by_cheese(x)); 39 | -------------------------------------------------------------------------------- /reasonbs/chapter04.re: -------------------------------------------------------------------------------- 1 | /* 4 */ 2 | type meza = 3 | | Shrimp 4 | | Calamari 5 | | Escargots 6 | | Hummus; 7 | 8 | /* 5 */ 9 | type main = 10 | | Steak 11 | | Ravioli 12 | | Chicken 13 | | Eggplant; 14 | 15 | type salad = 16 | | Green 17 | | Cucumber 18 | | Greek; 19 | 20 | /* 6 */ 21 | type dessert = 22 | | Sundae 23 | | Mousse 24 | | Torte; 25 | 26 | /* 25 */ 27 | let add_a_steak = 28 | fun 29 | | Shrimp => (Shrimp, Steak) 30 | | Calamari => (Calamari, Steak) 31 | | Escargots => (Escargots, Steak) 32 | | Hummus => (Hummus, Steak); 33 | 34 | /* 42 */ 35 | /* No way I'm typing all that */ 36 | 37 | /* 46 */ 38 | let eq_main = 39 | fun 40 | | (Steak, Steak) => true 41 | | (Ravioli, Ravioli) => true 42 | | (Chicken, Chicken) => true 43 | | (Eggplant, Eggplant) => true 44 | | (a_main, another_main) => false; 45 | 46 | /* 54 */ 47 | let has_steak = 48 | fun 49 | | (meza, Steak, dessert) => true 50 | | (meza, main, dessert) => false; 51 | 52 | /* 66 */ 53 | let has_steak: ((meza, main, dessert)) => bool = 54 | fun 55 | | (a, Steak, d) => true 56 | | (a, ns, d) => false; 57 | 58 | /* 67 */ 59 | let add_a_steak: meza => (meza, main) = x => (x, Steak); 60 | /* Shorter: */ 61 | let add_a_steak = (x: meza) => (x, Steak); 62 | -------------------------------------------------------------------------------- /reasonml/chapter-04.re: -------------------------------------------------------------------------------- 1 | /* 4 */ 2 | type meza = 3 | | Shrimp 4 | | Calamari 5 | | Escargots 6 | | Hummus; 7 | 8 | /* 5 */ 9 | type main = 10 | | Steak 11 | | Ravioli 12 | | Chicken 13 | | Eggplant; 14 | 15 | type salad = 16 | | Green 17 | | Cucumber 18 | | Greek; 19 | 20 | /* 6 */ 21 | type dessert = 22 | | Sundae 23 | | Mousse 24 | | Torte; 25 | 26 | /* 25 */ 27 | let add_a_steak = 28 | fun 29 | | Shrimp => (Shrimp, Steak) 30 | | Calamari => (Calamari, Steak) 31 | | Escargots => (Escargots, Steak) 32 | | Hummus => (Hummus, Steak); 33 | 34 | /* 42 */ 35 | /* No way I'm typing all that */ 36 | 37 | /* 46 */ 38 | let eq_main = 39 | fun 40 | | (Steak, Steak) => true 41 | | (Ravioli, Ravioli) => true 42 | | (Chicken, Chicken) => true 43 | | (Eggplant, Eggplant) => true 44 | | (a_main, another_main) => false; 45 | 46 | /* 54 */ 47 | let has_steak = 48 | fun 49 | | (meza, Steak, dessert) => true 50 | | (meza, main, dessert) => false; 51 | 52 | /* 66 */ 53 | let has_steak: ((meza, main, dessert)) => bool = 54 | fun 55 | | (a, Steak, d) => true 56 | | (a, ns, d) => false; 57 | 58 | /* 67 */ 59 | let add_a_steak: meza => (meza, main) = x => (x, Steak); 60 | /* Shorter: */ 61 | let add_a_steak = (x: meza) => (x, Steak); 62 | -------------------------------------------------------------------------------- /ocaml/chapter-02.ml: -------------------------------------------------------------------------------- 1 | (* 1 *) 2 | type shish_kebab = 3 | Skewer 4 | | Onion of shish_kebab 5 | | Lamb of shish_kebab 6 | | Tomato of shish_kebab 7 | 8 | (* 15 *) 9 | let rec only_onions = 10 | function 11 | Skewer -> true 12 | | Onion x -> only_onions x 13 | | Lamb x -> false 14 | | Tomato x -> false 15 | 16 | (* 63 *) 17 | let rec is_vegetarian = 18 | function 19 | Skewer -> true 20 | | Onion x -> is_vegetarian x 21 | | Lamb x -> false 22 | | Tomato x -> is_vegetarian x 23 | 24 | (* 64 *) 25 | type 'a shish = 26 | Bottom of 'a 27 | | Onion of 'a shish 28 | | Lamb of 'a shish 29 | | Tomato of 'a shish 30 | 31 | (* 67 *) 32 | type rod = Dagger | Fork | Sword 33 | 34 | (* 68 *) 35 | type plate = Gold_plate | Silver_plate | Brass_plate 36 | 37 | (* 73 *) 38 | let rec is_veggie = 39 | function 40 | Bottom x -> true 41 | | Onion x -> is_veggie x 42 | | Lamb x -> false 43 | | Tomato x -> is_veggie x 44 | 45 | (* 108 *) 46 | let rec what_bottom = 47 | function 48 | Bottom x -> x 49 | | Onion x -> what_bottom x 50 | | Lamb x -> what_bottom x 51 | | Tomato x -> what_bottom x 52 | (* Shorter version: *) 53 | let rec what_bottom = 54 | function 55 | Bottom x -> x 56 | | Onion x | Lamb x | Tomato x -> what_bottom x 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Little OCamler 2 | Most of the code examples from [The Little MLer](http://www.ccs.neu.edu/home/matthias/BTML/index.html), a wonderful book from the "Little `X`er" series, in **OCaml** and **ReasonML**. 3 | 4 | I thought other people who might have had the same idea as me might find it useful to have something to cross-reference, in case they get stuck because of some syntax idiosyncrasy in either SML or OCaml/ReasonML. 5 | 6 | Do not just copy-paste this code into the REPL. Type it yourself, and only consult this if you have trouble with the syntax. 7 | 8 | This is just a translation of the SML examples to OCaml, to the best of my efforts. Just don't expect idiomatic code or anything. 9 | 10 | ## But why? 11 | While I am sure SML is a great language, when I started reading *The Little MLer* I only had the OCaml compiler on my computer. 12 | 13 | Because I am a lazy person, I decided to take this as an opportunity to learn OCaml too. 14 | 15 | ## Now with ReasonML examples 16 | Thanks to @hzamir, a translation to ReasonML syntax has been added under the `reasonml/` directory. 17 | 18 | ## Now with ReasonML/Bucklescript examples 19 | A translation to ReasonML to JS compilations with Bucklescript has been added under the `reasonbs/` directory. 20 | 21 | To run `npm install` then `npm start`. 22 | -------------------------------------------------------------------------------- /reasonml/chapter-02.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type shish_kebab = 3 | | Skewer 4 | | Onion(shish_kebab) 5 | | Lamb(shish_kebab) 6 | | Tomato(shish_kebab); 7 | 8 | /* 15 */ 9 | let rec only_onions = 10 | fun 11 | | Skewer => true 12 | | Onion(x) => only_onions(x) 13 | | Lamb(x) => false 14 | | Tomato(x) => false; 15 | 16 | /* 63 */ 17 | let rec is_vegetarian = 18 | fun 19 | | Skewer => true 20 | | Onion(x) => is_vegetarian(x) 21 | | Lamb(x) => false 22 | | Tomato(x) => is_vegetarian(x); 23 | 24 | /* 64 */ 25 | type shish('a) = 26 | | Bottom('a) 27 | | Onion(shish('a)) 28 | | Lamb(shish('a)) 29 | | Tomato(shish('a)); 30 | 31 | /* 67 */ 32 | type rod = 33 | | Dagger 34 | | Fork 35 | | Sword; 36 | 37 | /* 68 */ 38 | type plate = 39 | | Gold_plate 40 | | Silver_plate 41 | | Brass_plate; 42 | 43 | /* 73 */ 44 | let rec is_veggie = 45 | fun 46 | | Bottom(x) => true 47 | | Onion(x) => is_veggie(x) 48 | | Lamb(x) => false 49 | | Tomato(x) => is_veggie(x); 50 | 51 | /* 108 */ 52 | let rec what_bottom = 53 | fun 54 | | Bottom(x) => x 55 | | Onion(x) => what_bottom(x) 56 | | Lamb(x) => what_bottom(x) 57 | | Tomato(x) => what_bottom(x); 58 | /* Shorter version: */ 59 | let rec what_bottom = 60 | fun 61 | | Bottom(x) => x 62 | | Onion(x) 63 | | Lamb(x) 64 | | Tomato(x) => what_bottom(x); 65 | -------------------------------------------------------------------------------- /reasonbs/chapter02.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type shish_kebab = 3 | | Skewer 4 | | Onion(shish_kebab) 5 | | Lamb(shish_kebab) 6 | | Tomato(shish_kebab); 7 | 8 | /* 15 */ 9 | let rec only_onions = 10 | fun 11 | | Skewer => true 12 | | Onion(x) => only_onions(x) 13 | | Lamb(_x) => false 14 | | Tomato(_x) => false; 15 | 16 | /* 63 */ 17 | let rec is_vegetarian = 18 | fun 19 | | Skewer => true 20 | | Onion(x) => is_vegetarian(x) 21 | | Lamb(_x) => false 22 | | Tomato(x) => is_vegetarian(x); 23 | 24 | /* 64 */ 25 | type shish('a) = 26 | | Bottom('a) 27 | | Onion(shish('a)) 28 | | Lamb(shish('a)) 29 | | Tomato(shish('a)); 30 | 31 | /* 67 */ 32 | type rod = 33 | | Dagger 34 | | Fork 35 | | Sword; 36 | 37 | /* 68 */ 38 | type plate = 39 | | Gold_plate 40 | | Silver_plate 41 | | Brass_plate; 42 | 43 | /* 73 */ 44 | let rec is_veggie = 45 | fun 46 | | Bottom(_x) => true 47 | | Onion(x) => is_veggie(x) 48 | | Lamb(_x) => false 49 | | Tomato(x) => is_veggie(x); 50 | 51 | /* 108 */ 52 | let rec what_bottom' = 53 | fun 54 | | Bottom(x) => x 55 | | Onion(x) => what_bottom'(x) 56 | | Lamb(x) => what_bottom'(x) 57 | | Tomato(x) => what_bottom'(x); 58 | /* Shorter version: */ 59 | let rec what_bottom = 60 | fun 61 | | Bottom(x) => x 62 | | Onion(x) 63 | | Lamb(x) 64 | | Tomato(x) => what_bottom(x); 65 | -------------------------------------------------------------------------------- /ocaml/chapter-09.ml: -------------------------------------------------------------------------------- 1 | (* 4 *) 2 | type 'a list = 3 | Empty 4 | | Cons of 'a * 'a list 5 | 6 | (* 5 *) 7 | type box = 8 | Bacon 9 | | Ix of int 10 | 11 | (* 9 *) 12 | let is_bacon = 13 | function 14 | Bacon -> true 15 | | Ix n -> false 16 | 17 | let rec where_is = 18 | function 19 | Empty -> 0 20 | | Cons (a_box, rest) -> 21 | if is_bacon a_box 22 | then 1 23 | else 1 + where_is rest 24 | 25 | (* 14 *) 26 | exception No_bacon of int 27 | 28 | let rec where_is = 29 | function 30 | Empty -> raise (No_bacon 0) 31 | | Cons (a_box, rest) -> 32 | if is_bacon a_box 33 | then 1 34 | else 1 + where_is rest 35 | 36 | (* 31 *) ;; 37 | (* The ;; above is required as the expression below isn't bound to 38 | * anything, so the compiler thinks it's part of the let above, 39 | * which is nonsense and leads to a syntax error. *) 40 | try (where_is (Cons (Ix 5, Cons (Ix 13, Cons (Ix 8, Empty))))) with 41 | No_bacon an_int -> an_int 42 | 43 | (* 66 *) 44 | let eq_int ((n : int), (m : int)) = (n = m) 45 | 46 | exception Out_of_range 47 | 48 | let rec list_item = 49 | function 50 | n, Empty -> raise Out_of_range 51 | | n, Cons (a_box, rest) -> 52 | if eq_int (n, 1) 53 | then a_box 54 | else list_item (n - 1, rest) 55 | 56 | (* 67 *) 57 | let rec find (n, boxes) = 58 | try check (n, boxes, list_item (n, boxes)) with 59 | Out_of_range -> find (n / 2, boxes) 60 | and check = 61 | function 62 | n, boxes, Bacon -> n 63 | | n, boxes, Ix i -> find (i, boxes) 64 | 65 | (* 75 *) 66 | let t = Cons (Ix 5, Cons (Ix 4, Cons (Bacon, 67 | Cons (Ix 2, Cons (Ix 3, Empty))))) 68 | 69 | (* 98 *) 70 | let rec path (n, boxes) = 71 | Cons (n, (try check (boxes, list_item (n, boxes)) with 72 | Out_of_range -> path (n / 2, boxes))) 73 | and check = 74 | function 75 | boxes, Bacon -> Empty 76 | | boxes, Ix i -> path (i, boxes) 77 | -------------------------------------------------------------------------------- /ocaml/chapter-07.ml: -------------------------------------------------------------------------------- 1 | (* 1 *) 2 | let identity x = x 3 | 4 | (* 5 *) 5 | let true_maker x = true 6 | 7 | (* 7 *) 8 | type bool_or_int = 9 | Hot of bool 10 | | Cold of int 11 | 12 | (* 11 *) 13 | (* Constructors are not functions in OCaml, 14 | * so the definition for this is a bit different. *) 15 | let hot_maker x = 16 | fun x -> Hot x 17 | 18 | (* 20 *) 19 | let help f = 20 | Hot (true_maker 21 | (if true_maker 5 22 | then f 23 | else true_maker)) 24 | 25 | (* 38 *) 26 | type chain = 27 | Link of int * (int -> chain) 28 | 29 | (* 50 *) 30 | let rec ints n = 31 | Link (n + 1, ints) 32 | 33 | (* 58 *) 34 | let rec skips n = 35 | Link (n + 2, ints) 36 | 37 | (* 61 *) 38 | let eq_int ((n : int), (m : int)) = (n = m) 39 | 40 | let divides_evenly (n, c) = 41 | eq_int ((n mod c), 0) 42 | 43 | let is_mod_5_or_7 n = 44 | divides_evenly (n, 5) || divides_evenly (n, 7) 45 | 46 | (* 62 *) 47 | let rec some_ints n = 48 | if is_mod_5_or_7 (n + 1) 49 | then Link (n + 1, some_ints) 50 | else some_ints (n + 1) 51 | 52 | (* 83 *) 53 | let rec chain_item = 54 | fun (n, Link (i, f)) -> 55 | if eq_int (n, 1) 56 | then i 57 | else chain_item (n - 1, f i) 58 | 59 | (* 93 *) 60 | let rec is_prime n = 61 | has_no_divisors (n, n - 1) 62 | and has_no_divisors (n, c) = 63 | eq_int (c, 1) || 64 | if divides_evenly (n, c) 65 | then false 66 | else has_no_divisors (n, c - 1) 67 | (* Nicer: *) 68 | let is_prime n = 69 | let rec has_no_divisors (n, c) = 70 | eq_int (c, 1) || 71 | if divides_evenly (n, c) 72 | then false 73 | else has_no_divisors (n, c - 1) 74 | in has_no_divisors (n, n - 1) 75 | 76 | (* 96 *) 77 | let rec primes n = 78 | if is_prime (n + 1) 79 | then Link (n + 1, primes) 80 | else primes (n + 1) 81 | 82 | (* 98 *) 83 | let rec fibs n m = 84 | Link (n + m, fibs m) 85 | 86 | (* 109 *) 87 | let fibs_1 m = 88 | Link (1 + m, fibs m) 89 | 90 | (* 117 *) 91 | let fibs_2 m = 92 | Link (2 + m, fibs m) 93 | -------------------------------------------------------------------------------- /ocaml/chapter-05.ml: -------------------------------------------------------------------------------- 1 | (* 1 *) 2 | type 'a pizza = 3 | Bottom 4 | | Topping of ('a * 'a pizza) 5 | 6 | (* 3 *) 7 | type fish = Anchovy | Lox | Tuna 8 | 9 | (* 11 *) 10 | let rec rem_anchovy = 11 | function 12 | Bottom -> Bottom 13 | | Topping (Anchovy, p) -> rem_anchovy p 14 | | Topping (Tuna, p) -> Topping (Tuna, rem_anchovy p) 15 | | Topping (Lox, p) -> Topping (Lox, rem_anchovy p) 16 | 17 | (* 13 *) 18 | let rec rem_anchovy = 19 | function 20 | Bottom -> Bottom 21 | | Topping (Anchovy, p) -> rem_anchovy p 22 | | Topping (t, p) -> Topping (t, rem_anchovy p) 23 | 24 | (* 14 *) 25 | let rec rem_tuna = 26 | function 27 | Bottom -> Bottom 28 | | Topping (Anchovy, p) -> Topping (Anchovy, rem_tuna p) 29 | | Topping (Tuna, p) -> rem_tuna p 30 | | Topping (Lox, p) -> Topping (Lox, rem_tuna p) 31 | 32 | (* 17 *) 33 | type fish = Tuna | Lox | Anchovy 34 | 35 | (* 21 *) 36 | let rec rem_tuna = 37 | function 38 | Bottom -> Bottom 39 | | Topping (Tuna, p) -> rem_tuna p 40 | | Topping (t, p) -> Topping (t, rem_tuna p) 41 | 42 | (* 38 *) 43 | let rec eq_fish = 44 | function 45 | Anchovy, Anchovy -> true 46 | | Lox, Lox -> true 47 | | Tuna, Tuna -> true 48 | | a_fish, another_fish -> false 49 | 50 | (* 40 *) 51 | let rec rem_fish = 52 | function 53 | x, Bottom -> Bottom 54 | | x, Topping (t, p) -> 55 | if eq_fish (t, x) 56 | then rem_fish (x, p) 57 | else Topping (t, (rem_fish (x, p))) 58 | 59 | (* 57 *) 60 | let eq_int ((n : int), (m : int)) = (n = m) 61 | (* This also works*) 62 | let eq_int : int * int -> bool = 63 | fun (n, m) -> (n = m) 64 | 65 | let rec rem_int = 66 | function 67 | x, Bottom -> Bottom 68 | | x, Topping (t, p) -> 69 | if eq_int (t, x) 70 | then rem_int (x, p) 71 | else Topping (t, (rem_int (x, p))) 72 | 73 | (* 66 *) 74 | let rec subst_fish = 75 | function 76 | n, a, Bottom -> Bottom 77 | | n, a, Topping (t, p) -> 78 | if eq_fish (t, a) 79 | then Topping (n, subst_fish (n, a, p)) 80 | else Topping (t, subst_fish (n, a, p)) 81 | 82 | let rec subst_int = 83 | function 84 | n, a, Bottom -> Bottom 85 | | n, a, Topping (t, p) -> 86 | if eq_int (t, a) 87 | then Topping (n, subst_int (n, a, p)) 88 | else Topping (t, subst_int (n, a, p)) 89 | 90 | (* 71 *) 91 | let rec eq_num = 92 | function 93 | Zero, Zero -> true 94 | | One_more_than n, One_more_than m -> eq_num (n, m) 95 | | n, m -> false 96 | -------------------------------------------------------------------------------- /reasonml/chapter-07.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | let identity = x => x; 3 | 4 | /* 5 */ 5 | let true_maker = x => true; 6 | 7 | /* 7 */ 8 | type bool_or_int = 9 | | Hot(bool) 10 | | Cold(int); 11 | 12 | /* 11 */ 13 | /* Constructors are not functions in OCaml, 14 | * so the definition for this is a bit different. */ 15 | let hot_maker = (x, x) => Hot(x); 16 | 17 | /* 20 */ 18 | let help = f => 19 | Hot( 20 | true_maker( 21 | if (true_maker(5)) { 22 | f; 23 | } else { 24 | true_maker; 25 | }, 26 | ), 27 | ); 28 | 29 | /* 38 */ 30 | type chain = 31 | | Link(int, int => chain); 32 | 33 | /* 50 */ 34 | let rec ints = n => [@implicit_arity] Link(n + 1, ints); 35 | 36 | /* 58 */ 37 | let rec skips = n => [@implicit_arity] Link(n + 2, ints); 38 | 39 | /* 61 */ 40 | let eq_int = ((n: int, m: int)) => n == m; 41 | 42 | let divides_evenly = ((n, c)) => eq_int((n mod c, 0)); 43 | 44 | let is_mod_5_or_7 = n => divides_evenly((n, 5)) || divides_evenly((n, 7)); 45 | 46 | /* 62 */ 47 | let rec some_ints = n => 48 | if (is_mod_5_or_7(n + 1)) { 49 | [@implicit_arity] Link(n + 1, some_ints); 50 | } else { 51 | some_ints(n + 1); 52 | }; 53 | 54 | /* 83 */ 55 | let rec chain_item = ((n, [@implicit_arity] Link(i, f))) => 56 | if (eq_int((n, 1))) { 57 | i; 58 | } else { 59 | chain_item((n - 1, f(i))); 60 | }; 61 | 62 | /* 93 */ 63 | let rec is_prime = n => has_no_divisors((n, n - 1)) 64 | and has_no_divisors = ((n, c)) => 65 | eq_int((c, 1)) 66 | || ( 67 | if (divides_evenly((n, c))) { 68 | false; 69 | } else { 70 | has_no_divisors((n, c - 1)); 71 | } 72 | ); 73 | /* Nicer: */ 74 | let is_prime = n => { 75 | let rec has_no_divisors = ((n, c)) => 76 | eq_int((c, 1)) 77 | || ( 78 | if (divides_evenly((n, c))) { 79 | false; 80 | } else { 81 | has_no_divisors((n, c - 1)); 82 | } 83 | ); 84 | has_no_divisors((n, n - 1)); 85 | }; 86 | 87 | /* 96 */ 88 | let rec primes = n => 89 | if (is_prime(n + 1)) { 90 | [@implicit_arity] Link(n + 1, primes); 91 | } else { 92 | primes(n + 1); 93 | }; 94 | 95 | /* 98 */ 96 | let rec fibs = (n, m) => [@implicit_arity] Link(n + m, fibs(m)); 97 | 98 | /* 109 */ 99 | let fibs_1 = m => [@implicit_arity] Link(1 + m, fibs(m)); 100 | 101 | /* 117 */ 102 | let fibs_2 = m => [@implicit_arity] Link(2 + m, fibs(m)); 103 | -------------------------------------------------------------------------------- /reasonbs/chapter07.re: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 1 */ 4 | let identity = x => x; 5 | 6 | /* 5 */ 7 | let true_maker = x => true; 8 | 9 | /* 7 */ 10 | type bool_or_int = 11 | | Hot(bool) 12 | | Cold(int); 13 | 14 | /* 11 */ 15 | /* Constructors are not functions in OCaml, 16 | * so the definition for this is a bit different. */ 17 | let hot_maker = (x, x) => Hot(x); 18 | 19 | /* 20 */ 20 | let help = f => 21 | Hot( 22 | true_maker( 23 | if (true_maker(5)) { 24 | f; 25 | } else { 26 | true_maker; 27 | }, 28 | ), 29 | ); 30 | 31 | /* 38 */ 32 | type chain = 33 | | Link(int, int => chain); 34 | 35 | /* 50 */ 36 | let rec ints = n => [@implicit_arity] Link(n + 1, ints); 37 | 38 | /* 58 */ 39 | let rec skips = n => [@implicit_arity] Link(n + 2, ints); 40 | 41 | /* 61 */ 42 | let eq_int = ((n: int, m: int)) => n == m; 43 | 44 | let divides_evenly = ((n, c)) => eq_int((n mod c, 0)); 45 | 46 | let is_mod_5_or_7 = n => divides_evenly((n, 5)) || divides_evenly((n, 7)); 47 | 48 | /* 62 */ 49 | let rec some_ints = n => 50 | if (is_mod_5_or_7(n + 1)) { 51 | [@implicit_arity] Link(n + 1, some_ints); 52 | } else { 53 | some_ints(n + 1); 54 | }; 55 | 56 | /* 83 */ 57 | let rec chain_item = ((n, [@implicit_arity] Link(i, f))) => 58 | if (eq_int((n, 1))) { 59 | i; 60 | } else { 61 | chain_item((n - 1, f(i))); 62 | }; 63 | 64 | /* 93 */ 65 | let rec is_prime = n => has_no_divisors((n, n - 1)) 66 | and has_no_divisors = ((n, c)) => 67 | eq_int((c, 1)) 68 | || ( 69 | if (divides_evenly((n, c))) { 70 | false; 71 | } else { 72 | has_no_divisors((n, c - 1)); 73 | } 74 | ); 75 | /* Nicer: */ 76 | let is_prime = n => { 77 | let rec has_no_divisors = ((n, c)) => 78 | eq_int((c, 1)) 79 | || ( 80 | if (divides_evenly((n, c))) { 81 | false; 82 | } else { 83 | has_no_divisors((n, c - 1)); 84 | } 85 | ); 86 | has_no_divisors((n, n - 1)); 87 | }; 88 | 89 | /* 96 */ 90 | let rec primes = n => 91 | if (is_prime(n + 1)) { 92 | [@implicit_arity] Link(n + 1, primes); 93 | } else { 94 | primes(n + 1); 95 | }; 96 | 97 | /* 98 */ 98 | let rec fibs = (n, m) => [@implicit_arity] Link(n + m, fibs(m)); 99 | 100 | /* 109 */ 101 | let fibs_1 = m => [@implicit_arity] Link(1 + m, fibs(m)); 102 | 103 | /* 117 */ 104 | let fibs_2 = m => [@implicit_arity] Link(2 + m, fibs(m)); 105 | -------------------------------------------------------------------------------- /reasonbs/chapter09.re: -------------------------------------------------------------------------------- 1 | /* 4 */ 2 | type list('a) = 3 | | Empty 4 | | Cons('a, list('a)); 5 | 6 | /* 5 */ 7 | type box = 8 | | Bacon 9 | | Ix(int); 10 | 11 | /* 9 */ 12 | let is_bacon = 13 | fun 14 | | Bacon => true 15 | | Ix(n) => false; 16 | 17 | let rec where_is = 18 | fun 19 | | Empty => 0 20 | | [@implicit_arity] Cons(a_box, rest) => 21 | if (is_bacon(a_box)) { 22 | 1; 23 | } else { 24 | 1 + where_is(rest); 25 | }; 26 | 27 | /* 14 */ 28 | exception No_bacon(int); 29 | 30 | let rec where_is = 31 | fun 32 | | Empty => raise(No_bacon(0)) 33 | | [@implicit_arity] Cons(a_box, rest) => 34 | if (is_bacon(a_box)) { 35 | 1; 36 | } else { 37 | 1 + where_is(rest); 38 | } /* 31 */; 39 | 40 | /* The ;; above is required as the expression below isn't bound to 41 | * anything, so the compiler thinks it's part of the let above, 42 | * which is nonsense and leads to a syntax error. */ 43 | try ( 44 | where_is( 45 | [@implicit_arity] 46 | Cons( 47 | Ix(5), 48 | [@implicit_arity] Cons(Ix(13), [@implicit_arity] Cons(Ix(8), Empty)), 49 | ), 50 | ) 51 | ) { 52 | | No_bacon(an_int) => an_int 53 | }; 54 | 55 | /* 66 */ 56 | let eq_int = ((n: int, m: int)) => n == m; 57 | 58 | exception Out_of_range; 59 | 60 | let rec list_item = 61 | fun 62 | | (n, Empty) => raise(Out_of_range) 63 | | (n, [@implicit_arity] Cons(a_box, rest)) => 64 | if (eq_int((n, 1))) { 65 | a_box; 66 | } else { 67 | list_item((n - 1, rest)); 68 | }; 69 | 70 | /* 67 */ 71 | let rec find = ((n, boxes)) => 72 | try (check((n, boxes, list_item((n, boxes))))) { 73 | | Out_of_range => find((n / 2, boxes)) 74 | } 75 | and check = 76 | fun 77 | | (n, boxes, Bacon) => n 78 | | (n, boxes, Ix(i)) => find((i, boxes)); 79 | 80 | /* 75 */ 81 | let t = 82 | [@implicit_arity] 83 | Cons( 84 | Ix(5), 85 | [@implicit_arity] 86 | Cons( 87 | Ix(4), 88 | [@implicit_arity] 89 | Cons( 90 | Bacon, 91 | [@implicit_arity] 92 | Cons(Ix(2), [@implicit_arity] Cons(Ix(3), Empty)), 93 | ), 94 | ), 95 | ); 96 | 97 | /* 98 */ 98 | let rec path = ((n, boxes)) => 99 | [@implicit_arity] 100 | Cons( 101 | n, 102 | try (check((boxes, list_item((n, boxes))))) { 103 | | Out_of_range => path((n / 2, boxes)) 104 | }, 105 | ) 106 | and check = 107 | fun 108 | | (boxes, Bacon) => Empty 109 | | (boxes, Ix(i)) => path((i, boxes)); 110 | -------------------------------------------------------------------------------- /reasonml/chapter-09.re: -------------------------------------------------------------------------------- 1 | /* 4 */ 2 | type list('a) = 3 | | Empty 4 | | Cons('a, list('a)); 5 | 6 | /* 5 */ 7 | type box = 8 | | Bacon 9 | | Ix(int); 10 | 11 | /* 9 */ 12 | let is_bacon = 13 | fun 14 | | Bacon => true 15 | | Ix(n) => false; 16 | 17 | let rec where_is = 18 | fun 19 | | Empty => 0 20 | | [@implicit_arity] Cons(a_box, rest) => 21 | if (is_bacon(a_box)) { 22 | 1; 23 | } else { 24 | 1 + where_is(rest); 25 | }; 26 | 27 | /* 14 */ 28 | exception No_bacon(int); 29 | 30 | let rec where_is = 31 | fun 32 | | Empty => raise(No_bacon(0)) 33 | | [@implicit_arity] Cons(a_box, rest) => 34 | if (is_bacon(a_box)) { 35 | 1; 36 | } else { 37 | 1 + where_is(rest); 38 | } /* 31 */; 39 | 40 | /* The ;; above is required as the expression below isn't bound to 41 | * anything, so the compiler thinks it's part of the let above, 42 | * which is nonsense and leads to a syntax error. */ 43 | try ( 44 | where_is( 45 | [@implicit_arity] 46 | Cons( 47 | Ix(5), 48 | [@implicit_arity] Cons(Ix(13), [@implicit_arity] Cons(Ix(8), Empty)), 49 | ), 50 | ) 51 | ) { 52 | | No_bacon(an_int) => an_int 53 | }; 54 | 55 | /* 66 */ 56 | let eq_int = ((n: int, m: int)) => n == m; 57 | 58 | exception Out_of_range; 59 | 60 | let rec list_item = 61 | fun 62 | | (n, Empty) => raise(Out_of_range) 63 | | (n, [@implicit_arity] Cons(a_box, rest)) => 64 | if (eq_int((n, 1))) { 65 | a_box; 66 | } else { 67 | list_item((n - 1, rest)); 68 | }; 69 | 70 | /* 67 */ 71 | let rec find = ((n, boxes)) => 72 | try (check((n, boxes, list_item((n, boxes))))) { 73 | | Out_of_range => find((n / 2, boxes)) 74 | } 75 | and check = 76 | fun 77 | | (n, boxes, Bacon) => n 78 | | (n, boxes, Ix(i)) => find((i, boxes)); 79 | 80 | /* 75 */ 81 | let t = 82 | [@implicit_arity] 83 | Cons( 84 | Ix(5), 85 | [@implicit_arity] 86 | Cons( 87 | Ix(4), 88 | [@implicit_arity] 89 | Cons( 90 | Bacon, 91 | [@implicit_arity] 92 | Cons(Ix(2), [@implicit_arity] Cons(Ix(3), Empty)), 93 | ), 94 | ), 95 | ); 96 | 97 | /* 98 */ 98 | let rec path = ((n, boxes)) => 99 | [@implicit_arity] 100 | Cons( 101 | n, 102 | try (check((boxes, list_item((n, boxes))))) { 103 | | Out_of_range => path((n / 2, boxes)) 104 | }, 105 | ) 106 | and check = 107 | fun 108 | | (boxes, Bacon) => Empty 109 | | (boxes, Ix(i)) => path((i, boxes)); 110 | -------------------------------------------------------------------------------- /ocaml/chapter-08.ml: -------------------------------------------------------------------------------- 1 | (* 1 *) 2 | type 'a list = 3 | Empty 4 | | Cons of 'a * 'a list 5 | 6 | let l = Cons (15, Cons (6, Cons (15, 7 | Cons (17, Cons (15, Cons (8, Empty)))))) 8 | 9 | (* 3 *) 10 | type orapl = Orange | Apple 11 | 12 | let eq_orapl = 13 | function 14 | Orange, Orange -> true 15 | | Apple, Apple -> true 16 | | one, another -> false 17 | 18 | (* 4 *) 19 | let rec subst_int = 20 | function 21 | n, a, Empty -> Empty 22 | | n, a, Cons (e, t) -> 23 | if eq_int (a, e) 24 | then Cons (n, subst_int (n, a, t)) 25 | else Cons (e, subst_int (n, a, t)) 26 | 27 | let rec subst_orapl = 28 | function 29 | n, a, Empty -> Empty 30 | | n, a, Cons (e, t) -> 31 | if eq_orapl (a, e) 32 | then Cons (n, subst_orapl (n, a, t)) 33 | else Cons (e, subst_orapl (n, a, t)) 34 | 35 | (* 9 *) 36 | let rec subst = 37 | function 38 | rel, n, a, Empty -> Empty 39 | | rel, n, a, Cons (e, t) -> 40 | if rel (a, e) 41 | then Cons (n, subst (rel, n, a, t)) 42 | else Cons (e, subst (rel, n, a, t)) 43 | 44 | (* 33 *) 45 | let less_than ((n : int), (m : int)) = 46 | (n < m) 47 | 48 | let in_range ((small, large), x) = 49 | less_than (small, x) && less_than (x, large) 50 | 51 | (* 40 *) 52 | let rec subst_pred = 53 | function 54 | pred, n, Empty -> Empty 55 | | pred, n, Cons (e, t) -> 56 | if pred e 57 | then Cons (n, subst_pred (pred, n, t)) 58 | else Cons (e, subst_pred (pred, n, t)) 59 | 60 | (* 48 *) 61 | let is_15 x = 62 | eq_int (x, 15) 63 | 64 | (* 52 *) 65 | let less_than_15 x = 66 | less_than (x, 15) 67 | 68 | (* 59 *) 69 | let in_range_11_16 x = 70 | less_than (11, x) && less_than (x, 16) 71 | 72 | (* 65 *) 73 | let in_range_c (small, large) x = 74 | less_than (small, x) && less_than (x, large) 75 | 76 | (* 79 *) 77 | let rec subst_c pred = 78 | function 79 | n, Empty -> Empty 80 | | n, Cons (e, t) -> 81 | if pred e 82 | then Cons (n, subst_c pred (n, t)) 83 | else Cons (e, subst_c pred (n, t)) 84 | 85 | (* 88 *) 86 | let rec combine = 87 | function 88 | Empty, Empty -> Empty 89 | | Empty, Cons (b, l2) -> Cons (b, l2) 90 | | Cons (a, l1), Empty -> Cons (a, l1) 91 | | Cons (a, l1), Cons (b, l2) -> 92 | Cons (a, combine (l1, Cons (b, l2))) 93 | 94 | let rec combine = 95 | function 96 | Empty, l2 -> l2 97 | | Cons (a, l1), l2 -> 98 | Cons (a, combine (l1, l2)) 99 | 100 | (* 93 *) 101 | let rec combine_c = 102 | function 103 | Empty -> fun l2 -> l2 104 | | Cons (a, l1) -> 105 | fun l2 -> 106 | Cons (a, combine_c l1 l2) 107 | 108 | (* 95 *) 109 | let prefixer_123 l2 = 110 | Cons (1, Cons (2, Cons (3, l2))) 111 | 112 | (* 97 *) 113 | let waiting_prefix_123 l2 = 114 | Cons (1, combine_c (Cons (2, Cons (3, Empty))) l2) 115 | 116 | (* 104 *) 117 | let base l2 = l2 118 | 119 | (* 115 *) 120 | let rec combine_s = 121 | function 122 | Empty -> base 123 | | Cons (a, l1) -> 124 | make_cons (a, combine_s l1) 125 | and make_cons (a, f) l2 = 126 | Cons (a, f l2) 127 | -------------------------------------------------------------------------------- /reasonml/chapter-05.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type pizza('a) = 3 | | Bottom 4 | | Topping(('a, pizza('a))); 5 | 6 | /* 3 */ 7 | type fish = 8 | | Anchovy 9 | | Lox 10 | | Tuna; 11 | 12 | /* 11 */ 13 | let rec rem_anchovy = 14 | fun 15 | | Bottom => Bottom 16 | | [@implicit_arity] Topping(Anchovy, p) => rem_anchovy(p) 17 | | [@implicit_arity] Topping(Tuna, p) => 18 | [@implicit_arity] Topping(Tuna, rem_anchovy(p)) 19 | | [@implicit_arity] Topping(Lox, p) => 20 | [@implicit_arity] Topping(Lox, rem_anchovy(p)); 21 | 22 | /* 13 */ 23 | let rec rem_anchovy = 24 | fun 25 | | Bottom => Bottom 26 | | [@implicit_arity] Topping(Anchovy, p) => rem_anchovy(p) 27 | | [@implicit_arity] Topping(t, p) => 28 | [@implicit_arity] Topping(t, rem_anchovy(p)); 29 | 30 | /* 14 */ 31 | let rec rem_tuna = 32 | fun 33 | | Bottom => Bottom 34 | | [@implicit_arity] Topping(Anchovy, p) => 35 | [@implicit_arity] Topping(Anchovy, rem_tuna(p)) 36 | | [@implicit_arity] Topping(Tuna, p) => rem_tuna(p) 37 | | [@implicit_arity] Topping(Lox, p) => 38 | [@implicit_arity] Topping(Lox, rem_tuna(p)); 39 | 40 | /* 17 */ 41 | type fish = 42 | | Tuna 43 | | Lox 44 | | Anchovy; 45 | 46 | /* 21 */ 47 | let rec rem_tuna = 48 | fun 49 | | Bottom => Bottom 50 | | [@implicit_arity] Topping(Tuna, p) => rem_tuna(p) 51 | | [@implicit_arity] Topping(t, p) => 52 | [@implicit_arity] Topping(t, rem_tuna(p)); 53 | 54 | /* 38 */ 55 | let rec eq_fish = 56 | fun 57 | | (Anchovy, Anchovy) => true 58 | | (Lox, Lox) => true 59 | | (Tuna, Tuna) => true 60 | | (a_fish, another_fish) => false; 61 | 62 | /* 40 */ 63 | let rec rem_fish = 64 | fun 65 | | (x, Bottom) => Bottom 66 | | (x, [@implicit_arity] Topping(t, p)) => 67 | if (eq_fish((t, x))) { 68 | rem_fish((x, p)); 69 | } else { 70 | [@implicit_arity] Topping(t, rem_fish((x, p))); 71 | }; 72 | 73 | /* 57 */ 74 | let eq_int = ((n: int, m: int)) => n == m; 75 | /* This also works*/ 76 | let eq_int: ((int, int)) => bool = ((n, m)) => n == m; 77 | 78 | let rec rem_int = 79 | fun 80 | | (x, Bottom) => Bottom 81 | | (x, [@implicit_arity] Topping(t, p)) => 82 | if (eq_int((t, x))) { 83 | rem_int((x, p)); 84 | } else { 85 | [@implicit_arity] Topping(t, rem_int((x, p))); 86 | }; 87 | 88 | /* 66 */ 89 | let rec subst_fish = 90 | fun 91 | | (n, a, Bottom) => Bottom 92 | | (n, a, [@implicit_arity] Topping(t, p)) => 93 | if (eq_fish((t, a))) { 94 | [@implicit_arity] Topping(n, subst_fish((n, a, p))); 95 | } else { 96 | [@implicit_arity] Topping(t, subst_fish((n, a, p))); 97 | }; 98 | 99 | let rec subst_int = 100 | fun 101 | | (n, a, Bottom) => Bottom 102 | | (n, a, [@implicit_arity] Topping(t, p)) => 103 | if (eq_int((t, a))) { 104 | [@implicit_arity] Topping(n, subst_int((n, a, p))); 105 | } else { 106 | [@implicit_arity] Topping(t, subst_int((n, a, p))); 107 | }; 108 | 109 | /* 71 */ 110 | let rec eq_num = 111 | fun 112 | | (Zero, Zero) => true 113 | | (One_more_than(n), One_more_than(m)) => eq_num((n, m)) 114 | | (n, m) => false; 115 | -------------------------------------------------------------------------------- /reasonbs/chapter05.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type pizza('a) = 3 | | Bottom 4 | | Topping(('a, pizza('a))); 5 | 6 | /* 3 */ 7 | type fish = 8 | | Anchovy 9 | | Lox 10 | | Tuna; 11 | 12 | /* 11 */ 13 | let rec rem_anchovy = 14 | fun 15 | | Bottom => Bottom 16 | | [@implicit_arity] Topping(Anchovy, p) => rem_anchovy(p) 17 | | [@implicit_arity] Topping(Tuna, p) => 18 | [@implicit_arity] Topping(Tuna, rem_anchovy(p)) 19 | | [@implicit_arity] Topping(Lox, p) => 20 | [@implicit_arity] Topping(Lox, rem_anchovy(p)); 21 | 22 | /* 13 */ 23 | let rec rem_anchovy = 24 | fun 25 | | Bottom => Bottom 26 | | [@implicit_arity] Topping(Anchovy, p) => rem_anchovy(p) 27 | | [@implicit_arity] Topping(t, p) => 28 | [@implicit_arity] Topping(t, rem_anchovy(p)); 29 | 30 | /* 14 */ 31 | let rec rem_tuna = 32 | fun 33 | | Bottom => Bottom 34 | | [@implicit_arity] Topping(Anchovy, p) => 35 | [@implicit_arity] Topping(Anchovy, rem_tuna(p)) 36 | | [@implicit_arity] Topping(Tuna, p) => rem_tuna(p) 37 | | [@implicit_arity] Topping(Lox, p) => 38 | [@implicit_arity] Topping(Lox, rem_tuna(p)); 39 | 40 | /* 17 */ 41 | type fish2 = 42 | | Tuna 43 | | Lox 44 | | Anchovy; 45 | 46 | /* 21 */ 47 | let rec rem_tuna = 48 | fun 49 | | Bottom => Bottom 50 | | [@implicit_arity] Topping(Tuna, p) => rem_tuna(p) 51 | | [@implicit_arity] Topping(t, p) => 52 | [@implicit_arity] Topping(t, rem_tuna(p)); 53 | 54 | /* 38 */ 55 | let rec eq_fish = 56 | fun 57 | | (Anchovy, Anchovy) => true 58 | | (Lox, Lox) => true 59 | | (Tuna, Tuna) => true 60 | | (a_fish, another_fish) => false; 61 | 62 | /* 40 */ 63 | let rec rem_fish = 64 | fun 65 | | (x, Bottom) => Bottom 66 | | (x, [@implicit_arity] Topping(t, p)) => 67 | if (eq_fish((t, x))) { 68 | rem_fish((x, p)); 69 | } else { 70 | [@implicit_arity] Topping(t, rem_fish((x, p))); 71 | }; 72 | 73 | /* 57 */ 74 | let eq_int = ((n: int, m: int)) => n == m; 75 | /* This also works*/ 76 | let eq_int: ((int, int)) => bool = ((n, m)) => n == m; 77 | 78 | let rec rem_int = 79 | fun 80 | | (x, Bottom) => Bottom 81 | | (x, [@implicit_arity] Topping(t, p)) => 82 | if (eq_int((t, x))) { 83 | rem_int((x, p)); 84 | } else { 85 | [@implicit_arity] Topping(t, rem_int((x, p))); 86 | }; 87 | 88 | /* 66 */ 89 | let rec subst_fish = 90 | fun 91 | | (n, a, Bottom) => Bottom 92 | | (n, a, [@implicit_arity] Topping(t, p)) => 93 | if (eq_fish((t, a))) { 94 | [@implicit_arity] Topping(n, subst_fish((n, a, p))); 95 | } else { 96 | [@implicit_arity] Topping(t, subst_fish((n, a, p))); 97 | }; 98 | 99 | let rec subst_int = 100 | fun 101 | | (n, a, Bottom) => Bottom 102 | | (n, a, [@implicit_arity] Topping(t, p)) => 103 | if (eq_int((t, a))) { 104 | [@implicit_arity] Topping(n, subst_int((n, a, p))); 105 | } else { 106 | [@implicit_arity] Topping(t, subst_int((n, a, p))); 107 | }; 108 | type num = 109 | | Zero 110 | | One_more_than(num); 111 | /* 71 */ 112 | let rec eq_num = 113 | fun 114 | | (Zero, Zero) => true 115 | | (One_more_than(n), One_more_than(m)) => eq_num((n, m)) 116 | | (_n, _m) => false; 117 | -------------------------------------------------------------------------------- /ocaml/chapter-06.ml: -------------------------------------------------------------------------------- 1 | (* 6 *) 2 | type fruit = Peach | Apple | Pear | Lemon | Fig 3 | 4 | type tree = 5 | Bud 6 | | Flat of fruit * tree 7 | | Split of tree * tree 8 | 9 | (* 11 *) 10 | let rec flat_only = 11 | function 12 | Bud -> true 13 | | Flat (f, t) -> flat_only t 14 | | Split (s, t) -> false 15 | 16 | (* 18 *) 17 | let rec split_only = 18 | function 19 | Bud -> true 20 | | Flat (f, t) -> false 21 | | Split (s, t) -> 22 | split_only s && split_only t 23 | 24 | (* 22 *) 25 | let rec contains_fruit = 26 | function 27 | Bud -> false 28 | | Flat (f, t) -> true 29 | | Split (s, t) -> 30 | contains_fruit s || contains_fruit t 31 | 32 | let contains_fruit x = 33 | not (split_only x) 34 | 35 | (* 34 *) 36 | let less_than ((n : int), (m : int)) = 37 | (n < m) 38 | 39 | let larger_of (n, m) = 40 | if less_than (n, m) 41 | then m 42 | else n 43 | 44 | (* 39 *) 45 | let eq_fruit = 46 | function 47 | Peach, Peach -> true 48 | | Apple, Apple -> true 49 | | Pear, Pear -> true 50 | | Lemon, Lemon -> true 51 | | Fig, Fig -> true 52 | | a_fruit, another_fruit -> false 53 | 54 | (* 41 *) 55 | let rec subst_in_tree = 56 | function 57 | n, a, Bud -> Bud 58 | | n, a, Flat (f, t) -> 59 | if eq_fruit (f, a) 60 | then Flat (n, subst_in_tree (n, a, t)) 61 | else Flat (f, subst_in_tree (n, a, t)) 62 | | n, a, Split (s, t) -> 63 | Split (subst_in_tree (n, a, s), 64 | subst_in_tree (n, a, t)) 65 | 66 | (* 43 *) 67 | let rec occurs = 68 | function 69 | n, Bud -> 0 70 | | n, Flat (f, t) -> 71 | if eq_fruit (n, f) 72 | then 1 + occurs (n, t) 73 | else occurs (n, t) 74 | | n, Split (s, t) -> 75 | occurs (n, s) + occurs (n, t) 76 | 77 | (* 51 *) 78 | type 'a slist = 79 | Empty 80 | | Scons of 'a sexp * 'a slist 81 | and 'a sexp = 82 | An_atom of 'a 83 | | A_slist of 'a slist 84 | 85 | (* 57 *) 86 | let rec occurs_in_slist = 87 | function 88 | a, Empty -> 0 89 | | a, Scons (s, y) -> 90 | occurs_in_sexp (a, s) + occurs_in_slist (a, y) 91 | and occurs_in_sexp = 92 | function 93 | a, An_atom b -> 94 | if eq_fruit (b, a) then 1 else 0 95 | | a, A_slist y -> occurs_in_slist (a, y) 96 | 97 | (* 58 *) 98 | let rec subst_in_slist = 99 | function 100 | n, a, Empty -> Empty 101 | | n, a, Scons (s, y) -> 102 | Scons (subst_in_sexp (n, a, s), 103 | subst_in_slist (n, a, y)) 104 | and subst_in_sexp = 105 | function 106 | n, a, An_atom b -> 107 | if eq_fruit (b, a) 108 | then An_atom n 109 | else An_atom b 110 | | n, a, A_slist y -> 111 | A_slist (subst_in_slist (n, a, y)) 112 | 113 | (* 65 *) 114 | let rec eq_fruit_in_atom = 115 | function 116 | a, An_atom s -> eq_fruit (a, s) 117 | | a_fruit, A_slist y -> false 118 | 119 | (* 68 *) 120 | let rec rem_from_slist = 121 | function 122 | a, Empty -> Empty 123 | | a, Scons (s, y) -> 124 | if eq_fruit_in_atom (a, s) 125 | then rem_from_slist (a, y) 126 | else Scons (rem_from_sexp (a, s), 127 | rem_from_slist (a, y)) 128 | and rem_from_sexp = 129 | function 130 | a, An_atom b -> An_atom b 131 | | a, A_slist y -> A_slist (rem_from_slist (a, y)) 132 | 133 | (* 76 *) 134 | let rec rem_from_slist = 135 | function 136 | a, Empty -> Empty 137 | | a, Scons (An_atom b, y) -> 138 | if eq_fruit (a, b) 139 | then rem_from_slist (a, y) 140 | else Scons (An_atom b, 141 | rem_from_slist (a, y)) 142 | | a, Scons (A_slist x, y) -> 143 | Scons (A_slist (rem_from_slist (a, x)), 144 | rem_from_slist (a, y)) 145 | -------------------------------------------------------------------------------- /reasonbs/chapter06.re: -------------------------------------------------------------------------------- 1 | /* 6 */ 2 | type fruit = 3 | | Peach 4 | | Apple 5 | | Pear 6 | | Lemon 7 | | Fig; 8 | 9 | type tree = 10 | | Bud 11 | | Flat(fruit, tree) 12 | | Split(tree, tree); 13 | 14 | /* 11 */ 15 | let rec flat_only = 16 | fun 17 | | Bud => true 18 | | [@implicit_arity] Flat(f, t) => flat_only(t) 19 | | [@implicit_arity] Split(s, t) => false; 20 | 21 | /* 18 */ 22 | let rec split_only = 23 | fun 24 | | Bud => true 25 | | [@implicit_arity] Flat(f, t) => false 26 | | [@implicit_arity] Split(s, t) => split_only(s) && split_only(t); 27 | 28 | /* 22 */ 29 | let rec contains_fruit = 30 | fun 31 | | Bud => false 32 | | [@implicit_arity] Flat(f, t) => true 33 | | [@implicit_arity] Split(s, t) => contains_fruit(s) || contains_fruit(t); 34 | 35 | let contains_fruit = x => !split_only(x); 36 | 37 | /* 34 */ 38 | let less_than = ((n: int, m: int)) => n < m; 39 | 40 | let larger_of = ((n, m)) => 41 | if (less_than((n, m))) { 42 | m; 43 | } else { 44 | n; 45 | }; 46 | 47 | /* 39 */ 48 | let eq_fruit = 49 | fun 50 | | (Peach, Peach) => true 51 | | (Apple, Apple) => true 52 | | (Pear, Pear) => true 53 | | (Lemon, Lemon) => true 54 | | (Fig, Fig) => true 55 | | (a_fruit, another_fruit) => false; 56 | 57 | /* 41 */ 58 | let rec subst_in_tree = 59 | fun 60 | | (n, a, Bud) => Bud 61 | | (n, a, [@implicit_arity] Flat(f, t)) => 62 | if (eq_fruit((f, a))) { 63 | [@implicit_arity] Flat(n, subst_in_tree((n, a, t))); 64 | } else { 65 | [@implicit_arity] Flat(f, subst_in_tree((n, a, t))); 66 | } 67 | | (n, a, [@implicit_arity] Split(s, t)) => 68 | [@implicit_arity] 69 | Split(subst_in_tree((n, a, s)), subst_in_tree((n, a, t))); 70 | 71 | /* 43 */ 72 | let rec occurs = 73 | fun 74 | | (n, Bud) => 0 75 | | (n, [@implicit_arity] Flat(f, t)) => 76 | if (eq_fruit((n, f))) { 77 | 1 + occurs((n, t)); 78 | } else { 79 | occurs((n, t)); 80 | } 81 | | (n, [@implicit_arity] Split(s, t)) => occurs((n, s)) + occurs((n, t)); 82 | 83 | /* 51 */ 84 | type slist('a) = 85 | | Empty 86 | | Scons(sexp('a), slist('a)) 87 | and sexp('a) = 88 | | An_atom('a) 89 | | A_slist(slist('a)); 90 | 91 | /* 57 */ 92 | let rec occurs_in_slist = 93 | fun 94 | | (a, Empty) => 0 95 | | (a, [@implicit_arity] Scons(s, y)) => 96 | occurs_in_sexp((a, s)) + occurs_in_slist((a, y)) 97 | and occurs_in_sexp = 98 | fun 99 | | (a, An_atom(b)) => 100 | if (eq_fruit((b, a))) { 101 | 1; 102 | } else { 103 | 0; 104 | } 105 | | (a, A_slist(y)) => occurs_in_slist((a, y)); 106 | 107 | /* 58 */ 108 | let rec subst_in_slist = 109 | fun 110 | | (n, a, Empty) => Empty 111 | | (n, a, [@implicit_arity] Scons(s, y)) => 112 | [@implicit_arity] 113 | Scons(subst_in_sexp((n, a, s)), subst_in_slist((n, a, y))) 114 | and subst_in_sexp = 115 | fun 116 | | (n, a, An_atom(b)) => 117 | if (eq_fruit((b, a))) { 118 | An_atom(n); 119 | } else { 120 | An_atom(b); 121 | } 122 | | (n, a, A_slist(y)) => A_slist(subst_in_slist((n, a, y))); 123 | 124 | /* 65 */ 125 | let rec eq_fruit_in_atom = 126 | fun 127 | | (a, An_atom(s)) => eq_fruit((a, s)) 128 | | (a_fruit, A_slist(y)) => false; 129 | 130 | /* 68 */ 131 | let rec rem_from_slist = 132 | fun 133 | | (a, Empty) => Empty 134 | | (a, [@implicit_arity] Scons(s, y)) => 135 | if (eq_fruit_in_atom((a, s))) { 136 | rem_from_slist((a, y)); 137 | } else { 138 | [@implicit_arity] 139 | Scons(rem_from_sexp((a, s)), rem_from_slist((a, y))); 140 | } 141 | and rem_from_sexp = 142 | fun 143 | | (a, An_atom(b)) => An_atom(b) 144 | | (a, A_slist(y)) => A_slist(rem_from_slist((a, y))); 145 | 146 | /* 76 */ 147 | let rec rem_from_slist = 148 | fun 149 | | (a, Empty) => Empty 150 | | (a, [@implicit_arity] Scons(An_atom(b), y)) => 151 | if (eq_fruit((a, b))) { 152 | rem_from_slist((a, y)); 153 | } else { 154 | [@implicit_arity] Scons(An_atom(b), rem_from_slist((a, y))); 155 | } 156 | | (a, [@implicit_arity] Scons(A_slist(x), y)) => 157 | [@implicit_arity] 158 | Scons(A_slist(rem_from_slist((a, x))), rem_from_slist((a, y))); 159 | -------------------------------------------------------------------------------- /reasonml/chapter-06.re: -------------------------------------------------------------------------------- 1 | /* 6 */ 2 | type fruit = 3 | | Peach 4 | | Apple 5 | | Pear 6 | | Lemon 7 | | Fig; 8 | 9 | type tree = 10 | | Bud 11 | | Flat(fruit, tree) 12 | | Split(tree, tree); 13 | 14 | /* 11 */ 15 | let rec flat_only = 16 | fun 17 | | Bud => true 18 | | [@implicit_arity] Flat(f, t) => flat_only(t) 19 | | [@implicit_arity] Split(s, t) => false; 20 | 21 | /* 18 */ 22 | let rec split_only = 23 | fun 24 | | Bud => true 25 | | [@implicit_arity] Flat(f, t) => false 26 | | [@implicit_arity] Split(s, t) => split_only(s) && split_only(t); 27 | 28 | /* 22 */ 29 | let rec contains_fruit = 30 | fun 31 | | Bud => false 32 | | [@implicit_arity] Flat(f, t) => true 33 | | [@implicit_arity] Split(s, t) => contains_fruit(s) || contains_fruit(t); 34 | 35 | let contains_fruit = x => !split_only(x); 36 | 37 | /* 34 */ 38 | let less_than = ((n: int, m: int)) => n < m; 39 | 40 | let larger_of = ((n, m)) => 41 | if (less_than((n, m))) { 42 | m; 43 | } else { 44 | n; 45 | }; 46 | 47 | /* 39 */ 48 | let eq_fruit = 49 | fun 50 | | (Peach, Peach) => true 51 | | (Apple, Apple) => true 52 | | (Pear, Pear) => true 53 | | (Lemon, Lemon) => true 54 | | (Fig, Fig) => true 55 | | (a_fruit, another_fruit) => false; 56 | 57 | /* 41 */ 58 | let rec subst_in_tree = 59 | fun 60 | | (n, a, Bud) => Bud 61 | | (n, a, [@implicit_arity] Flat(f, t)) => 62 | if (eq_fruit((f, a))) { 63 | [@implicit_arity] Flat(n, subst_in_tree((n, a, t))); 64 | } else { 65 | [@implicit_arity] Flat(f, subst_in_tree((n, a, t))); 66 | } 67 | | (n, a, [@implicit_arity] Split(s, t)) => 68 | [@implicit_arity] 69 | Split(subst_in_tree((n, a, s)), subst_in_tree((n, a, t))); 70 | 71 | /* 43 */ 72 | let rec occurs = 73 | fun 74 | | (n, Bud) => 0 75 | | (n, [@implicit_arity] Flat(f, t)) => 76 | if (eq_fruit((n, f))) { 77 | 1 + occurs((n, t)); 78 | } else { 79 | occurs((n, t)); 80 | } 81 | | (n, [@implicit_arity] Split(s, t)) => occurs((n, s)) + occurs((n, t)); 82 | 83 | /* 51 */ 84 | type slist('a) = 85 | | Empty 86 | | Scons(sexp('a), slist('a)) 87 | and sexp('a) = 88 | | An_atom('a) 89 | | A_slist(slist('a)); 90 | 91 | /* 57 */ 92 | let rec occurs_in_slist = 93 | fun 94 | | (a, Empty) => 0 95 | | (a, [@implicit_arity] Scons(s, y)) => 96 | occurs_in_sexp((a, s)) + occurs_in_slist((a, y)) 97 | and occurs_in_sexp = 98 | fun 99 | | (a, An_atom(b)) => 100 | if (eq_fruit((b, a))) { 101 | 1; 102 | } else { 103 | 0; 104 | } 105 | | (a, A_slist(y)) => occurs_in_slist((a, y)); 106 | 107 | /* 58 */ 108 | let rec subst_in_slist = 109 | fun 110 | | (n, a, Empty) => Empty 111 | | (n, a, [@implicit_arity] Scons(s, y)) => 112 | [@implicit_arity] 113 | Scons(subst_in_sexp((n, a, s)), subst_in_slist((n, a, y))) 114 | and subst_in_sexp = 115 | fun 116 | | (n, a, An_atom(b)) => 117 | if (eq_fruit((b, a))) { 118 | An_atom(n); 119 | } else { 120 | An_atom(b); 121 | } 122 | | (n, a, A_slist(y)) => A_slist(subst_in_slist((n, a, y))); 123 | 124 | /* 65 */ 125 | let rec eq_fruit_in_atom = 126 | fun 127 | | (a, An_atom(s)) => eq_fruit((a, s)) 128 | | (a_fruit, A_slist(y)) => false; 129 | 130 | /* 68 */ 131 | let rec rem_from_slist = 132 | fun 133 | | (a, Empty) => Empty 134 | | (a, [@implicit_arity] Scons(s, y)) => 135 | if (eq_fruit_in_atom((a, s))) { 136 | rem_from_slist((a, y)); 137 | } else { 138 | [@implicit_arity] 139 | Scons(rem_from_sexp((a, s)), rem_from_slist((a, y))); 140 | } 141 | and rem_from_sexp = 142 | fun 143 | | (a, An_atom(b)) => An_atom(b) 144 | | (a, A_slist(y)) => A_slist(rem_from_slist((a, y))); 145 | 146 | /* 76 */ 147 | let rec rem_from_slist = 148 | fun 149 | | (a, Empty) => Empty 150 | | (a, [@implicit_arity] Scons(An_atom(b), y)) => 151 | if (eq_fruit((a, b))) { 152 | rem_from_slist((a, y)); 153 | } else { 154 | [@implicit_arity] Scons(An_atom(b), rem_from_slist((a, y))); 155 | } 156 | | (a, [@implicit_arity] Scons(A_slist(x), y)) => 157 | [@implicit_arity] 158 | Scons(A_slist(rem_from_slist((a, x))), rem_from_slist((a, y))); 159 | -------------------------------------------------------------------------------- /reasonml/chapter-08.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type list('a) = 3 | | Empty 4 | | Cons('a, list('a)); 5 | 6 | let l = 7 | [@implicit_arity] 8 | Cons( 9 | 15, 10 | [@implicit_arity] 11 | Cons( 12 | 6, 13 | [@implicit_arity] 14 | Cons( 15 | 15, 16 | [@implicit_arity] 17 | Cons( 18 | 17, 19 | [@implicit_arity] Cons(15, [@implicit_arity] Cons(8, Empty)), 20 | ), 21 | ), 22 | ), 23 | ); 24 | 25 | /* 3 */ 26 | type orapl = 27 | | Orange 28 | | Apple; 29 | 30 | let eq_orapl = 31 | fun 32 | | (Orange, Orange) => true 33 | | (Apple, Apple) => true 34 | | (one, another) => false; 35 | 36 | /* 4 */ 37 | let rec subst_int = 38 | fun 39 | | (n, a, Empty) => Empty 40 | | (n, a, [@implicit_arity] Cons(e, t)) => 41 | if (eq_int((a, e))) { 42 | [@implicit_arity] Cons(n, subst_int((n, a, t))); 43 | } else { 44 | [@implicit_arity] Cons(e, subst_int((n, a, t))); 45 | }; 46 | 47 | let rec subst_orapl = 48 | fun 49 | | (n, a, Empty) => Empty 50 | | (n, a, [@implicit_arity] Cons(e, t)) => 51 | if (eq_orapl((a, e))) { 52 | [@implicit_arity] Cons(n, subst_orapl((n, a, t))); 53 | } else { 54 | [@implicit_arity] Cons(e, subst_orapl((n, a, t))); 55 | }; 56 | 57 | /* 9 */ 58 | let rec subst = 59 | fun 60 | | (rel, n, a, Empty) => Empty 61 | | (rel, n, a, [@implicit_arity] Cons(e, t)) => 62 | if (rel((a, e))) { 63 | [@implicit_arity] Cons(n, subst((rel, n, a, t))); 64 | } else { 65 | [@implicit_arity] Cons(e, subst((rel, n, a, t))); 66 | }; 67 | 68 | /* 33 */ 69 | let less_than = ((n: int, m: int)) => n < m; 70 | 71 | let in_range = (((small, large), x)) => 72 | less_than((small, x)) && less_than((x, large)); 73 | 74 | /* 40 */ 75 | let rec subst_pred = 76 | fun 77 | | (pred, n, Empty) => Empty 78 | | (pred, n, [@implicit_arity] Cons(e, t)) => 79 | if (pred(e)) { 80 | [@implicit_arity] Cons(n, subst_pred((pred, n, t))); 81 | } else { 82 | [@implicit_arity] Cons(e, subst_pred((pred, n, t))); 83 | }; 84 | 85 | /* 48 */ 86 | let is_15 = x => eq_int((x, 15)); 87 | 88 | /* 52 */ 89 | let less_than_15 = x => less_than((x, 15)); 90 | 91 | /* 59 */ 92 | let in_range_11_16 = x => less_than((11, x)) && less_than((x, 16)); 93 | 94 | /* 65 */ 95 | let in_range_c = ((small, large), x) => 96 | less_than((small, x)) && less_than((x, large)); 97 | 98 | /* 79 */ 99 | let rec subst_c = pred => 100 | fun 101 | | (n, Empty) => Empty 102 | | (n, [@implicit_arity] Cons(e, t)) => 103 | if (pred(e)) { 104 | [@implicit_arity] Cons(n, subst_c(pred, (n, t))); 105 | } else { 106 | [@implicit_arity] Cons(e, subst_c(pred, (n, t))); 107 | }; 108 | 109 | /* 88 */ 110 | let rec combine = 111 | fun 112 | | (Empty, Empty) => Empty 113 | | (Empty, [@implicit_arity] Cons(b, l2)) => [@implicit_arity] Cons(b, l2) 114 | | ([@implicit_arity] Cons(a, l1), Empty) => [@implicit_arity] Cons(a, l1) 115 | | ([@implicit_arity] Cons(a, l1), [@implicit_arity] Cons(b, l2)) => 116 | [@implicit_arity] Cons(a, combine((l1, [@implicit_arity] Cons(b, l2)))); 117 | 118 | let rec combine = 119 | fun 120 | | (Empty, l2) => l2 121 | | ([@implicit_arity] Cons(a, l1), l2) => 122 | [@implicit_arity] Cons(a, combine((l1, l2))); 123 | 124 | /* 93 */ 125 | let rec combine_c = 126 | fun 127 | | Empty => (l2 => l2) 128 | | [@implicit_arity] Cons(a, l1) => ( 129 | l2 => [@implicit_arity] Cons(a, combine_c(l1, l2)) 130 | ); 131 | 132 | /* 95 */ 133 | let prefixer_123 = l2 => 134 | [@implicit_arity] 135 | Cons(1, [@implicit_arity] Cons(2, [@implicit_arity] Cons(3, l2))); 136 | 137 | /* 97 */ 138 | let waiting_prefix_123 = l2 => 139 | [@implicit_arity] 140 | Cons( 141 | 1, 142 | combine_c( 143 | [@implicit_arity] Cons(2, [@implicit_arity] Cons(3, Empty)), 144 | l2, 145 | ), 146 | ); 147 | 148 | /* 104 */ 149 | let base = l2 => l2; 150 | 151 | /* 115 */ 152 | let rec combine_s = 153 | fun 154 | | Empty => base 155 | | [@implicit_arity] Cons(a, l1) => make_cons((a, combine_s(l1))) 156 | and make_cons = ((a, f), l2) => [@implicit_arity] Cons(a, f(l2)); 157 | -------------------------------------------------------------------------------- /reasonbs/chapter08.re: -------------------------------------------------------------------------------- 1 | /* 1 */ 2 | type list('a) = 3 | | Empty 4 | | Cons('a, list('a)); 5 | let eq_int = ((n: int, m: int)) => n == m; 6 | let l = 7 | [@implicit_arity] 8 | Cons( 9 | 15, 10 | [@implicit_arity] 11 | Cons( 12 | 6, 13 | [@implicit_arity] 14 | Cons( 15 | 15, 16 | [@implicit_arity] 17 | Cons( 18 | 17, 19 | [@implicit_arity] Cons(15, [@implicit_arity] Cons(8, Empty)), 20 | ), 21 | ), 22 | ), 23 | ); 24 | 25 | /* 3 */ 26 | type orapl = 27 | | Orange 28 | | Apple; 29 | 30 | let eq_orapl = 31 | fun 32 | | (Orange, Orange) => true 33 | | (Apple, Apple) => true 34 | | (one, another) => false; 35 | 36 | /* 4 */ 37 | let rec subst_int = 38 | fun 39 | | (n, a, Empty) => Empty 40 | | (n, a, [@implicit_arity] Cons(e, t)) => 41 | if (eq_int((a, e))) { 42 | [@implicit_arity] Cons(n, subst_int((n, a, t))); 43 | } else { 44 | [@implicit_arity] Cons(e, subst_int((n, a, t))); 45 | }; 46 | 47 | let rec subst_orapl = 48 | fun 49 | | (n, a, Empty) => Empty 50 | | (n, a, [@implicit_arity] Cons(e, t)) => 51 | if (eq_orapl((a, e))) { 52 | [@implicit_arity] Cons(n, subst_orapl((n, a, t))); 53 | } else { 54 | [@implicit_arity] Cons(e, subst_orapl((n, a, t))); 55 | }; 56 | 57 | /* 9 */ 58 | let rec subst = 59 | fun 60 | | (rel, n, a, Empty) => Empty 61 | | (rel, n, a, [@implicit_arity] Cons(e, t)) => 62 | if (rel((a, e))) { 63 | [@implicit_arity] Cons(n, subst((rel, n, a, t))); 64 | } else { 65 | [@implicit_arity] Cons(e, subst((rel, n, a, t))); 66 | }; 67 | 68 | /* 33 */ 69 | let less_than = ((n: int, m: int)) => n < m; 70 | 71 | let in_range = (((small, large), x)) => 72 | less_than((small, x)) && less_than((x, large)); 73 | 74 | /* 40 */ 75 | let rec subst_pred = 76 | fun 77 | | (pred, n, Empty) => Empty 78 | | (pred, n, [@implicit_arity] Cons(e, t)) => 79 | if (pred(e)) { 80 | [@implicit_arity] Cons(n, subst_pred((pred, n, t))); 81 | } else { 82 | [@implicit_arity] Cons(e, subst_pred((pred, n, t))); 83 | }; 84 | 85 | /* 48 */ 86 | let is_15 = x => eq_int((x, 15)); 87 | 88 | /* 52 */ 89 | let less_than_15 = x => less_than((x, 15)); 90 | 91 | /* 59 */ 92 | let in_range_11_16 = x => less_than((11, x)) && less_than((x, 16)); 93 | 94 | /* 65 */ 95 | let in_range_c = ((small, large), x) => 96 | less_than((small, x)) && less_than((x, large)); 97 | 98 | /* 79 */ 99 | let rec subst_c = pred => 100 | fun 101 | | (n, Empty) => Empty 102 | | (n, [@implicit_arity] Cons(e, t)) => 103 | if (pred(e)) { 104 | [@implicit_arity] Cons(n, subst_c(pred, (n, t))); 105 | } else { 106 | [@implicit_arity] Cons(e, subst_c(pred, (n, t))); 107 | }; 108 | 109 | /* 88 */ 110 | let rec combine = 111 | fun 112 | | (Empty, Empty) => Empty 113 | | (Empty, [@implicit_arity] Cons(b, l2)) => [@implicit_arity] Cons(b, l2) 114 | | ([@implicit_arity] Cons(a, l1), Empty) => [@implicit_arity] Cons(a, l1) 115 | | ([@implicit_arity] Cons(a, l1), [@implicit_arity] Cons(b, l2)) => 116 | [@implicit_arity] Cons(a, combine((l1, [@implicit_arity] Cons(b, l2)))); 117 | 118 | // no [@implicit_arity] still compiles and gets the rec recognized. 119 | let rec combine2 = 120 | fun 121 | | (Empty, Empty) => Empty 122 | | (Empty, Cons(b, l2)) => Cons(b, l2) 123 | | ( Cons(a, l1), Empty) => Cons(a, l1) 124 | | ( Cons(a, l1), Cons(b, l2)) => 125 | Cons(a, combine2((l1, Cons(b, l2)))); 126 | 127 | let rec combine = 128 | fun 129 | | (Empty, l2) => l2 130 | | ([@implicit_arity] Cons(a, l1), l2) => 131 | [@implicit_arity] Cons(a, combine((l1, l2))); 132 | 133 | /* 93 */ 134 | let rec combine_c = 135 | fun 136 | | Empty => (l2 => l2) 137 | | [@implicit_arity] Cons(a, l1) => ( 138 | l2 => [@implicit_arity] Cons(a, combine_c(l1, l2)) 139 | ); 140 | 141 | /* 95 */ 142 | let prefixer_123 = l2 => 143 | [@implicit_arity] 144 | Cons(1, [@implicit_arity] Cons(2, [@implicit_arity] Cons(3, l2))); 145 | 146 | /* 97 */ 147 | let waiting_prefix_123 = l2 => 148 | [@implicit_arity] 149 | Cons( 150 | 1, 151 | combine_c( 152 | [@implicit_arity] Cons(2, [@implicit_arity] Cons(3, Empty)), 153 | l2, 154 | ), 155 | ); 156 | 157 | /* 104 */ 158 | let base = l2 => l2; 159 | 160 | /* 115 */ 161 | let rec combine_s = 162 | fun 163 | | Empty => base 164 | | [@implicit_arity] Cons(a, l1) => make_cons((a, combine_s(l1))) 165 | and make_cons = ((a, f), l2) => [@implicit_arity] Cons(a, f(l2)); 166 | -------------------------------------------------------------------------------- /ocaml/chapter-10.ml: -------------------------------------------------------------------------------- 1 | let eq_int ((n : int), (m : int)) = n = m 2 | 3 | (* 4 *) 4 | exception Too_small 5 | 6 | let is_zero n = eq_int (n, 0) 7 | 8 | let pred n = 9 | if is_zero n 10 | then raise Too_small 11 | else n - 1 12 | 13 | let succ n = n + 1 14 | 15 | let rec plus (n, m) = 16 | if is_zero n 17 | then m 18 | else succ (plus (pred n, m)) 19 | 20 | (* 5 *) 21 | type num = 22 | Zero 23 | | One_more_than of num 24 | 25 | let is_zero = 26 | function 27 | Zero -> true 28 | | not_zero -> false 29 | 30 | let pred = 31 | function 32 | Zero -> raise Too_small 33 | | One_more_than n -> n 34 | 35 | let succ n = One_more_than n 36 | 37 | let rec plus (n, m) = 38 | if is_zero n 39 | then m 40 | else succ (plus (pred n, m)) 41 | 42 | (* 18 *) 43 | module type N = sig 44 | type number 45 | exception Too_small 46 | val succ : number -> number 47 | val pred : number -> number 48 | val is_zero : number -> bool 49 | end 50 | 51 | (* 26 *) 52 | module NumberAsNum0 ( ) : N = struct 53 | type num = 54 | Zero 55 | | One_more_than of num 56 | type number = num 57 | exception Too_small 58 | let succ n = 59 | One_more_than n 60 | let pred = 61 | function 62 | Zero -> raise Too_small 63 | | One_more_than n -> n 64 | let is_zero = 65 | function 66 | Zero -> true 67 | | a_num -> false 68 | end 69 | 70 | module NumberAsInt0 ( ) : N = struct 71 | type number = int 72 | exception Too_small 73 | let succ n = n + 1 74 | let pred n = 75 | if eq_int (n, 0) 76 | then raise Too_small 77 | else n - 1 78 | let is_zero n = 79 | eq_int (n, 0) 80 | end 81 | 82 | (* 33 *) 83 | module IntStruct0 = NumberAsInt0( ) 84 | 85 | (* 35 *) 86 | module NumStruct0 = NumberAsNum0( ) 87 | 88 | (* 40 *) 89 | module type P = sig 90 | type number 91 | val plus : number * number -> number 92 | end 93 | 94 | (* 41 *) 95 | module PON (Na : N) : P = struct 96 | type number = Na.number 97 | let rec plus (n, m) = 98 | if Na.is_zero m 99 | then m 100 | else Na.succ (plus (Na.pred n, m)) 101 | end 102 | 103 | (* 47 *) 104 | module IntArith0 = PON(IntStruct0) 105 | 106 | (* 62 *) 107 | module type N_C_R = sig 108 | type number 109 | exception Too_small 110 | val conceal : int -> number 111 | val reveal : number -> int 112 | val is_zero : number -> bool 113 | val succ : number -> number 114 | val pred : number -> number 115 | end 116 | 117 | (* 65 *) 118 | module NumberAsInt ( ) : N_C_R = struct 119 | type number = int 120 | exception Too_small 121 | let conceal n = n 122 | let reveal n = n 123 | let is_zero n = eq_int (n, 0) 124 | let succ n = n + 1 125 | let pred n = 126 | if is_zero n then raise Too_small else n - 1 127 | end 128 | 129 | module NumberAsNum ( ) : N_C_R = struct 130 | type number = Zero | One_more_than of number 131 | exception Too_small 132 | let rec conceal n = 133 | if eq_int (n, 0) 134 | then Zero 135 | else One_more_than (conceal (n - 1)) 136 | let rec reveal = function 137 | | Zero -> 0 138 | | One_more_than n -> 1 + (reveal n) 139 | let is_zero = function Zero -> true | _ -> false 140 | let succ n = One_more_than n 141 | let pred = function 142 | | Zero -> raise Too_small 143 | | One_more_than n -> n 144 | end 145 | 146 | (* 66 *) 147 | module IntStruct = NumberAsInt( ) 148 | 149 | module IntArith = PON(IntStruct) 150 | 151 | module NumStruct = NumberAsNum( ) 152 | 153 | module NumArith = PON(NumStruct) 154 | 155 | (* 93 *) 156 | module NumberAsInt2 ( ) 157 | : N with type number = int 158 | = struct 159 | type number = int 160 | exception Too_small 161 | let is_zero n = eq_int (n, 0) 162 | let succ n = n + 1 163 | let pred n = 164 | if is_zero n then raise Too_small else n - 1 165 | end 166 | 167 | (* 95 *) 168 | module IntStruct2 = NumberAsInt2( ) 169 | 170 | (* 96 *) 171 | module IntArith2 = PON(IntStruct2) 172 | 173 | (* 114 *) 174 | module type S = sig 175 | type number1 176 | type number2 177 | val similar : number1 * number2 -> bool 178 | end 179 | 180 | (* 115 *) 181 | module Same (Na : N) (Nb: N) 182 | : S with type number1 = Na.number 183 | with type number2 = Nb.number 184 | = struct 185 | type number1 = Na.number 186 | type number2 = Nb.number 187 | let rec sim (n, m) = 188 | if Na.is_zero n 189 | then Nb.is_zero m 190 | else sim (Na.pred n, Nb.pred m) 191 | let similar (n, m) = 192 | try sim (n, m) with 193 | | Na.Too_small -> false 194 | | Nb.Too_small -> false 195 | end 196 | 197 | (* 118 *) 198 | module SimIntNum = Same(IntStruct)(NumStruct) 199 | 200 | (* 119 *) 201 | module SimNumInt = Same(NumStruct)(IntStruct) 202 | 203 | (* 127 *) 204 | (* Can't reproduce in OCaml *) 205 | 206 | (* 129 *) 207 | module type J = sig 208 | val new_plus : int * int -> int 209 | end 210 | 211 | module NP (Na : N_C_R with type number = int) 212 | (Pa : P with type number = int) 213 | : J = struct 214 | let new_plus (x, y) = 215 | Na.reveal 216 | (Pa.plus 217 | ( Na.conceal x 218 | , Na.conceal y )) 219 | end 220 | 221 | (* Can't reproduce *) 222 | module NPStruct = NP(struct 223 | type number = int 224 | exception Too_small 225 | let conceal n = n 226 | let reveal n = n 227 | let is_zero n = eq_int (n, 0) 228 | let succ n = n + 1 229 | let pred n = 230 | if is_zero n then raise Too_small else n - 1 231 | end)(struct 232 | type number = int 233 | let rec plus (x, y) = 234 | x + y 235 | end) 236 | 237 | (* 147 *) 238 | module type T = sig 239 | type number 240 | val times : number * number -> number 241 | end 242 | 243 | (* 244 | module TON (Na : N) (Pa : P) 245 | : T with type number = Na.number 246 | = struct 247 | type number = Na.number 248 | let rec times (n, m) = 249 | if Na.is_zero m 250 | then m 251 | else Pa.plus (n, times (n, Na.pred m)) 252 | end 253 | *) 254 | -------------------------------------------------------------------------------- /reasonbs/chapter10.re: -------------------------------------------------------------------------------- 1 | let eq_int = ((n: int, m: int)) => n == m; 2 | 3 | /* 4 */ 4 | exception Too_small; 5 | 6 | let is_zero = n => eq_int((n, 0)); 7 | 8 | let pred = n => 9 | if (is_zero(n)) { 10 | raise(Too_small); 11 | } else { 12 | n - 1; 13 | }; 14 | 15 | let succ = n => n + 1; 16 | 17 | let rec plus = ((n, m)) => 18 | if (is_zero(n)) { 19 | m; 20 | } else { 21 | succ(plus((pred(n), m))); 22 | }; 23 | 24 | /* 5 */ 25 | type num = 26 | | Zero 27 | | One_more_than(num); 28 | 29 | let is_zero = 30 | fun 31 | | Zero => true 32 | | not_zero => false; 33 | 34 | let pred = 35 | fun 36 | | Zero => raise(Too_small) 37 | | One_more_than(n) => n; 38 | 39 | let succ = n => One_more_than(n); 40 | 41 | let rec plus = ((n, m)) => 42 | if (is_zero(n)) { 43 | m; 44 | } else { 45 | succ(plus((pred(n), m))); 46 | }; 47 | 48 | /* 18 */ 49 | module type N = { 50 | type number; 51 | exception Too_small; 52 | let succ: number => number; 53 | let pred: number => number; 54 | let is_zero: number => bool; 55 | }; 56 | 57 | /* 26 */ 58 | module NumberAsNum0 = (()) : N => { 59 | type num = 60 | | Zero 61 | | One_more_than(num); 62 | type number = num; 63 | exception Too_small; 64 | let succ = n => One_more_than(n); 65 | let pred = 66 | fun 67 | | Zero => raise(Too_small) 68 | | One_more_than(n) => n; 69 | let is_zero = 70 | fun 71 | | Zero => true 72 | | a_num => false; 73 | }; 74 | 75 | module NumberAsInt0 = (()) : N => { 76 | type number = int; 77 | exception Too_small; 78 | let succ = n => n + 1; 79 | let pred = n => 80 | if (eq_int((n, 0))) { 81 | raise(Too_small); 82 | } else { 83 | n - 1; 84 | }; 85 | let is_zero = n => eq_int((n, 0)); 86 | }; 87 | 88 | /* 33 */ 89 | module IntStruct0 = 90 | NumberAsInt0({}); 91 | 92 | /* 35 */ 93 | module NumStruct0 = 94 | NumberAsNum0({}); 95 | 96 | /* 40 */ 97 | module type P = { 98 | type number; 99 | let plus: ((number, number)) => number; 100 | }; 101 | 102 | /* 41 */ 103 | module PON = (Na: N) : P => { 104 | type number = Na.number; 105 | let rec plus = ((n, m)) => 106 | if (Na.is_zero(m)) { 107 | m; 108 | } else { 109 | Na.succ(plus((Na.pred(n), m))); 110 | }; 111 | }; 112 | 113 | /* 47 */ 114 | module IntArith0 = PON(IntStruct0); 115 | 116 | /* 62 */ 117 | module type N_C_R = { 118 | type number; 119 | exception Too_small; 120 | let conceal: int => number; 121 | let reveal: number => int; 122 | let is_zero: number => bool; 123 | let succ: number => number; 124 | let pred: number => number; 125 | }; 126 | 127 | /* 65 */ 128 | module NumberAsInt = (()) : N_C_R => { 129 | type number = int; 130 | exception Too_small; 131 | let conceal = n => n; 132 | let reveal = n => n; 133 | let is_zero = n => eq_int((n, 0)); 134 | let succ = n => n + 1; 135 | let pred = n => 136 | if (is_zero(n)) { 137 | raise(Too_small); 138 | } else { 139 | n - 1; 140 | }; 141 | }; 142 | 143 | module NumberAsNum = (()) : N_C_R => { 144 | type number = 145 | | Zero 146 | | One_more_than(number); 147 | exception Too_small; 148 | let rec conceal = n => 149 | if (eq_int((n, 0))) { 150 | Zero; 151 | } else { 152 | One_more_than(conceal(n - 1)); 153 | }; 154 | let rec reveal = 155 | fun 156 | | Zero => 0 157 | | One_more_than(n) => 1 + reveal(n); 158 | let is_zero = 159 | fun 160 | | Zero => true 161 | | _ => false; 162 | let succ = n => One_more_than(n); 163 | let pred = 164 | fun 165 | | Zero => raise(Too_small) 166 | | One_more_than(n) => n; 167 | }; 168 | 169 | /* 66 */ 170 | module IntStruct = 171 | NumberAsInt({}); 172 | 173 | module IntArith = PON(IntStruct); 174 | 175 | module NumStruct = 176 | NumberAsNum({}); 177 | 178 | module NumArith = PON(NumStruct); 179 | 180 | /* 93 */ 181 | module NumberAsInt2 = (()) : (N with type number = int) => { 182 | type number = int; 183 | exception Too_small; 184 | let is_zero = n => eq_int((n, 0)); 185 | let succ = n => n + 1; 186 | let pred = n => 187 | if (is_zero(n)) { 188 | raise(Too_small); 189 | } else { 190 | n - 1; 191 | }; 192 | }; 193 | 194 | /* 95 */ 195 | module IntStruct2 = 196 | NumberAsInt2({}); 197 | 198 | /* 96 */ 199 | module IntArith2 = PON(IntStruct2); 200 | 201 | /* 114 */ 202 | module type S = { 203 | type number1; 204 | type number2; 205 | let similar: ((number1, number2)) => bool; 206 | }; 207 | 208 | /* 115 */ 209 | module Same = 210 | (Na: N, Nb: N) 211 | : (S with type number1 = Na.number with type number2 = Nb.number) => { 212 | type number1 = Na.number; 213 | type number2 = Nb.number; 214 | let rec sim = ((n, m)) => 215 | if (Na.is_zero(n)) { 216 | Nb.is_zero(m); 217 | } else { 218 | sim((Na.pred(n), Nb.pred(m))); 219 | }; 220 | let similar = ((n, m)) => 221 | try (sim((n, m))) { 222 | | Na.Too_small => false 223 | | Nb.Too_small => false 224 | }; 225 | }; 226 | 227 | /* 118 */ 228 | module SimIntNum = Same(IntStruct, NumStruct); 229 | 230 | /* 119 */ 231 | module SimNumInt = Same(NumStruct, IntStruct); 232 | 233 | /* 127 */ 234 | /* Can't reproduce in OCaml */ 235 | 236 | /* 129 */ 237 | module type J = {let new_plus: ((int, int)) => int;}; 238 | 239 | module NP = 240 | (Na: N_C_R with type number = int, Pa: P with type number = int) 241 | : J => { 242 | let new_plus = ((x, y)) => 243 | Na.reveal(Pa.plus((Na.conceal(x), Na.conceal(y)))); 244 | }; 245 | 246 | /* Can't reproduce */ 247 | module NPStruct = 248 | NP( 249 | { 250 | type number = int; 251 | exception Too_small; 252 | let conceal = n => n; 253 | let reveal = n => n; 254 | let is_zero = n => eq_int((n, 0)); 255 | let succ = n => n + 1; 256 | let pred = n => 257 | if (is_zero(n)) { 258 | raise(Too_small); 259 | } else { 260 | n - 1; 261 | }; 262 | }, 263 | { 264 | type number = int; 265 | let rec plus = ((x, y)) => x + y; 266 | }, 267 | ); 268 | 269 | /* 147 */ 270 | module type T = { 271 | type number; 272 | let times: ((number, number)) => number; 273 | }; 274 | 275 | /* 276 | module TON (Na : N) (Pa : P) 277 | : T with type number = Na.number 278 | = struct 279 | type number = Na.number 280 | let rec times (n, m) = 281 | if Na.is_zero m 282 | then m 283 | else Pa.plus (n, times (n, Na.pred m)) 284 | end 285 | */ 286 | -------------------------------------------------------------------------------- /reasonml/chapter-10.re: -------------------------------------------------------------------------------- 1 | let eq_int = ((n: int, m: int)) => n == m; 2 | 3 | /* 4 */ 4 | exception Too_small; 5 | 6 | let is_zero = n => eq_int((n, 0)); 7 | 8 | let pred = n => 9 | if (is_zero(n)) { 10 | raise(Too_small); 11 | } else { 12 | n - 1; 13 | }; 14 | 15 | let succ = n => n + 1; 16 | 17 | let rec plus = ((n, m)) => 18 | if (is_zero(n)) { 19 | m; 20 | } else { 21 | succ(plus((pred(n), m))); 22 | }; 23 | 24 | /* 5 */ 25 | type num = 26 | | Zero 27 | | One_more_than(num); 28 | 29 | let is_zero = 30 | fun 31 | | Zero => true 32 | | not_zero => false; 33 | 34 | let pred = 35 | fun 36 | | Zero => raise(Too_small) 37 | | One_more_than(n) => n; 38 | 39 | let succ = n => One_more_than(n); 40 | 41 | let rec plus = ((n, m)) => 42 | if (is_zero(n)) { 43 | m; 44 | } else { 45 | succ(plus((pred(n), m))); 46 | }; 47 | 48 | /* 18 */ 49 | module type N = { 50 | type number; 51 | exception Too_small; 52 | let succ: number => number; 53 | let pred: number => number; 54 | let is_zero: number => bool; 55 | }; 56 | 57 | /* 26 */ 58 | module NumberAsNum0 = (()) : N => { 59 | type num = 60 | | Zero 61 | | One_more_than(num); 62 | type number = num; 63 | exception Too_small; 64 | let succ = n => One_more_than(n); 65 | let pred = 66 | fun 67 | | Zero => raise(Too_small) 68 | | One_more_than(n) => n; 69 | let is_zero = 70 | fun 71 | | Zero => true 72 | | a_num => false; 73 | }; 74 | 75 | module NumberAsInt0 = (()) : N => { 76 | type number = int; 77 | exception Too_small; 78 | let succ = n => n + 1; 79 | let pred = n => 80 | if (eq_int((n, 0))) { 81 | raise(Too_small); 82 | } else { 83 | n - 1; 84 | }; 85 | let is_zero = n => eq_int((n, 0)); 86 | }; 87 | 88 | /* 33 */ 89 | module IntStruct0 = 90 | NumberAsInt0({}); 91 | 92 | /* 35 */ 93 | module NumStruct0 = 94 | NumberAsNum0({}); 95 | 96 | /* 40 */ 97 | module type P = { 98 | type number; 99 | let plus: ((number, number)) => number; 100 | }; 101 | 102 | /* 41 */ 103 | module PON = (Na: N) : P => { 104 | type number = Na.number; 105 | let rec plus = ((n, m)) => 106 | if (Na.is_zero(m)) { 107 | m; 108 | } else { 109 | Na.succ(plus((Na.pred(n), m))); 110 | }; 111 | }; 112 | 113 | /* 47 */ 114 | module IntArith0 = PON(IntStruct0); 115 | 116 | /* 62 */ 117 | module type N_C_R = { 118 | type number; 119 | exception Too_small; 120 | let conceal: int => number; 121 | let reveal: number => int; 122 | let is_zero: number => bool; 123 | let succ: number => number; 124 | let pred: number => number; 125 | }; 126 | 127 | /* 65 */ 128 | module NumberAsInt = (()) : N_C_R => { 129 | type number = int; 130 | exception Too_small; 131 | let conceal = n => n; 132 | let reveal = n => n; 133 | let is_zero = n => eq_int((n, 0)); 134 | let succ = n => n + 1; 135 | let pred = n => 136 | if (is_zero(n)) { 137 | raise(Too_small); 138 | } else { 139 | n - 1; 140 | }; 141 | }; 142 | 143 | module NumberAsNum = (()) : N_C_R => { 144 | type number = 145 | | Zero 146 | | One_more_than(number); 147 | exception Too_small; 148 | let rec conceal = n => 149 | if (eq_int((n, 0))) { 150 | Zero; 151 | } else { 152 | One_more_than(conceal(n - 1)); 153 | }; 154 | let rec reveal = 155 | fun 156 | | Zero => 0 157 | | One_more_than(n) => 1 + reveal(n); 158 | let is_zero = 159 | fun 160 | | Zero => true 161 | | _ => false; 162 | let succ = n => One_more_than(n); 163 | let pred = 164 | fun 165 | | Zero => raise(Too_small) 166 | | One_more_than(n) => n; 167 | }; 168 | 169 | /* 66 */ 170 | module IntStruct = 171 | NumberAsInt({}); 172 | 173 | module IntArith = PON(IntStruct); 174 | 175 | module NumStruct = 176 | NumberAsNum({}); 177 | 178 | module NumArith = PON(NumStruct); 179 | 180 | /* 93 */ 181 | module NumberAsInt2 = (()) : (N with type number = int) => { 182 | type number = int; 183 | exception Too_small; 184 | let is_zero = n => eq_int((n, 0)); 185 | let succ = n => n + 1; 186 | let pred = n => 187 | if (is_zero(n)) { 188 | raise(Too_small); 189 | } else { 190 | n - 1; 191 | }; 192 | }; 193 | 194 | /* 95 */ 195 | module IntStruct2 = 196 | NumberAsInt2({}); 197 | 198 | /* 96 */ 199 | module IntArith2 = PON(IntStruct2); 200 | 201 | /* 114 */ 202 | module type S = { 203 | type number1; 204 | type number2; 205 | let similar: ((number1, number2)) => bool; 206 | }; 207 | 208 | /* 115 */ 209 | module Same = 210 | (Na: N, Nb: N) 211 | : (S with type number1 = Na.number with type number2 = Nb.number) => { 212 | type number1 = Na.number; 213 | type number2 = Nb.number; 214 | let rec sim = ((n, m)) => 215 | if (Na.is_zero(n)) { 216 | Nb.is_zero(m); 217 | } else { 218 | sim((Na.pred(n), Nb.pred(m))); 219 | }; 220 | let similar = ((n, m)) => 221 | try (sim((n, m))) { 222 | | Na.Too_small => false 223 | | Nb.Too_small => false 224 | }; 225 | }; 226 | 227 | /* 118 */ 228 | module SimIntNum = Same(IntStruct, NumStruct); 229 | 230 | /* 119 */ 231 | module SimNumInt = Same(NumStruct, IntStruct); 232 | 233 | /* 127 */ 234 | /* Can't reproduce in OCaml */ 235 | 236 | /* 129 */ 237 | module type J = {let new_plus: ((int, int)) => int;}; 238 | 239 | module NP = 240 | (Na: N_C_R with type number = int, Pa: P with type number = int) 241 | : J => { 242 | let new_plus = ((x, y)) => 243 | Na.reveal(Pa.plus((Na.conceal(x), Na.conceal(y)))); 244 | }; 245 | 246 | /* Can't reproduce */ 247 | module NPStruct = 248 | NP( 249 | { 250 | type number = int; 251 | exception Too_small; 252 | let conceal = n => n; 253 | let reveal = n => n; 254 | let is_zero = n => eq_int((n, 0)); 255 | let succ = n => n + 1; 256 | let pred = n => 257 | if (is_zero(n)) { 258 | raise(Too_small); 259 | } else { 260 | n - 1; 261 | }; 262 | }, 263 | { 264 | type number = int; 265 | let rec plus = ((x, y)) => x + y; 266 | }, 267 | ); 268 | 269 | /* 147 */ 270 | module type T = { 271 | type number; 272 | let times: ((number, number)) => number; 273 | }; 274 | 275 | /* 276 | module TON (Na : N) (Pa : P) 277 | : T with type number = Na.number 278 | = struct 279 | type number = Na.number 280 | let rec times (n, m) = 281 | if Na.is_zero m 282 | then m 283 | else Pa.plus (n, times (n, Na.pred m)) 284 | end 285 | */ 286 | --------------------------------------------------------------------------------