option monad, and some design changes
This commit is contained in:
parent
1c94d51334
commit
de837bbf3b
@ -12,6 +12,7 @@ This library includes the following custom modules:
|
|||||||
|
|
||||||
- Int (exposure of basic integer arithmetic functions)
|
- Int (exposure of basic integer arithmetic functions)
|
||||||
- Float (exposure of basic float arithmetic functions)
|
- Float (exposure of basic float arithmetic functions)
|
||||||
|
- Option (functions for working with the option monad)
|
||||||
- List (functional list data structure)
|
- List (functional list data structure)
|
||||||
- Queue (functional queue implemented as two lists)
|
- Queue (functional queue implemented as two lists)
|
||||||
- Set (functional set implemented as a red-black tree)
|
- Set (functional set implemented as a red-black tree)
|
||||||
@ -21,13 +22,13 @@ This library includes the following custom modules:
|
|||||||
|
|
||||||
## Exposure of Functions from Standard Library
|
## Exposure of Functions from Standard Library
|
||||||
|
|
||||||
With respect to the exposed parts of the standard library, these are all handled in the `FromStdlib` module, which redefines some definitions directly from the standard library so that this file can be safely included separately, exposing only the desired functions. As such, it is recommended that this file is opened in the code that uses this library, while others are not, and referenced from the module level instead (with one additional exception of `Types`, mentioned in the following section).
|
With respect to the exposed parts of the standard library, these are all handled in the `FromStdlib` module, which redefines some definitions directly from the standard library so that this file can be safely included separately, exposing only the desired functions. As such, it is recommended that this file is opened in the code that uses this library, while others are not, and referenced from the module level instead (with one additional exception of `Exposed`, mentioned in the following section).
|
||||||
|
|
||||||
All files are compiled with `-nopervasives` except `FromStdlib` (to avoid the headaches in exposing functions like `printf` which have many dependencies). Linking is also done without `-nopervasives` so that `fromStdlib.cmx` can find the corresponding functions. Hence any new files added to the project are recommended to be compiled separately with `nopervasives` and then linked via the `.cmx` file.
|
All files are compiled with `-nopervasives` except `FromStdlib` (to avoid the headaches in exposing functions like `printf` which have many dependencies). Linking is also done without `-nopervasives` so that `fromStdlib.cmx` can find the corresponding functions. Hence any new files added to the project are recommended to be compiled separately with `nopervasives` and then linked via the `.cmx` file.
|
||||||
|
|
||||||
## Type Declarations
|
## Type Declarations and General Functions
|
||||||
|
|
||||||
In order to prevent duplicate definitions of common types like collections, but still allow things like list literals to work, and to prevent the need of a type annotation at the module level, a `Types` module is provided to be opened in code files which exposes types like `'a queue` and other collections.
|
In order to prevent duplicate definitions of common types like collections, but still allow things like list literals to work, and to prevent the need of a type annotation at the module level, a `Exposed` module is provided to be opened in code files which exposes types like `'a queue` and other collections. `Exposed` also includes generic operators that should be opened file wide, such as function composition (`>>`).
|
||||||
|
|
||||||
## Build Process
|
## Build Process
|
||||||
|
|
||||||
|
@ -11,3 +11,10 @@ type 'a stack =
|
|||||||
type 'a tree =
|
type 'a tree =
|
||||||
| Leaf
|
| Leaf
|
||||||
| Branch of 'a * 'a tree list
|
| Branch of 'a * 'a tree list
|
||||||
|
|
||||||
|
|
||||||
|
let id (x : 'a) = x
|
||||||
|
|
||||||
|
let ( >> ) f g x = g (f x)
|
||||||
|
|
||||||
|
let ( << ) g f x = g (f x)
|
@ -14,3 +14,12 @@ type 'a stack =
|
|||||||
type 'a tree =
|
type 'a tree =
|
||||||
| Leaf
|
| Leaf
|
||||||
| Branch of 'a * 'a tree list
|
| Branch of 'a * 'a tree list
|
||||||
|
|
||||||
|
(** Identity function. *)
|
||||||
|
val id : 'a -> 'a
|
||||||
|
|
||||||
|
(** Function composition. (f >> g) x represents g (f x). *)
|
||||||
|
val ( >> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
|
||||||
|
|
||||||
|
(** Function composition. (f << g) x represents f (g x). *)
|
||||||
|
val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
|
@ -1,5 +0,0 @@
|
|||||||
let id (x : 'a) = x
|
|
||||||
|
|
||||||
let ( >> ) f g x = g (f x)
|
|
||||||
|
|
||||||
let ( << ) g f x = g (f x)
|
|
@ -1,8 +0,0 @@
|
|||||||
(** Identity function. *)
|
|
||||||
val id : 'a -> 'a
|
|
||||||
|
|
||||||
(** Function composition. (f >> g) x represents g (f x). *)
|
|
||||||
val ( >> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
|
|
||||||
|
|
||||||
(** Function composition. (f << g) x represents f (g x). *)
|
|
||||||
val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
|
|
@ -1,5 +1,5 @@
|
|||||||
open FromStdlib
|
open FromStdlib
|
||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
let empty : 'a list = []
|
let empty : 'a list = []
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
(** The empty list *)
|
(** The empty list *)
|
||||||
val empty : 'a list
|
val empty : 'a list
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
open FromStdlib open Types
|
open FromStdlib open Exposed
|
||||||
|
|
||||||
let _ = printf "Hello, World\n"
|
let _ = printf "Hello, World\n"
|
@ -4,14 +4,13 @@ build:
|
|||||||
ocamlopt -i fromStdlib.ml > fromStdlib.mli
|
ocamlopt -i fromStdlib.ml > fromStdlib.mli
|
||||||
ocamlopt -S -O3 -c fromStdlib.mli fromStdlib.ml
|
ocamlopt -S -O3 -c fromStdlib.mli fromStdlib.ml
|
||||||
|
|
||||||
# types for other modules separated to easily expose without module reference in projects
|
# exposed types and functions, that can be opened module wide
|
||||||
ocamlopt -S -O3 -nopervasives -c types.mli types.ml
|
ocamlopt -S -O3 -nopervasives -c exposed.mli exposed.ml
|
||||||
|
|
||||||
# the following files make up the core custom standard library code
|
# the following files make up the core custom standard library code
|
||||||
ocamlopt -S -O3 -nopervasives -c int.mli int.ml
|
ocamlopt -S -O3 -nopervasives -c int.mli int.ml
|
||||||
ocamlopt -S -O3 -nopervasives -c float.mli float.ml
|
ocamlopt -S -O3 -nopervasives -c float.mli float.ml
|
||||||
ocamlopt -S -O3 -nopervasives -c float.mli float.ml
|
ocamlopt -S -O3 -nopervasives -c option.mli option.ml
|
||||||
ocamlopt -S -O3 -nopervasives -c functions.mli functions.ml
|
|
||||||
ocamlopt -S -O3 -nopervasives -c stack.mli stack.ml
|
ocamlopt -S -O3 -nopervasives -c stack.mli stack.ml
|
||||||
ocamlopt -S -O3 -nopervasives -c list.mli list.ml
|
ocamlopt -S -O3 -nopervasives -c list.mli list.ml
|
||||||
ocamlopt -S -O3 -nopervasives -c map.mli map.ml
|
ocamlopt -S -O3 -nopervasives -c map.mli map.ml
|
||||||
@ -24,7 +23,7 @@ build:
|
|||||||
ocamlopt -S -O3 -nopervasives -c main.mli main.ml
|
ocamlopt -S -O3 -nopervasives -c main.mli main.ml
|
||||||
|
|
||||||
# after all files are individually compiled with -nopervasives, this is compiled with it so that fromStdlib has the necessary linking
|
# after all files are individually compiled with -nopervasives, this is compiled with it so that fromStdlib has the necessary linking
|
||||||
ocamlopt -S -O3 fromStdlib.cmx types.cmx int.cmx float.cmx functions.cmx stack.cmx list.cmx map.cmx queue.cmx set.cmx tree.cmx main.cmx -o program
|
ocamlopt -S -O3 fromStdlib.cmx exposed.cmx int.cmx float.cmx option.cmx stack.cmx list.cmx map.cmx queue.cmx set.cmx tree.cmx main.cmx -o program
|
||||||
|
|
||||||
# clean removes all except source files. autogenerated mli files are also removed.
|
# clean removes all except source files. autogenerated mli files are also removed.
|
||||||
clean:
|
clean:
|
||||||
|
23
lib/option.ml
Normal file
23
lib/option.ml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
open Exposed
|
||||||
|
|
||||||
|
let return (x : 'a) : 'a option = Some x
|
||||||
|
|
||||||
|
let ( ~= ) = return
|
||||||
|
|
||||||
|
let bind (x : 'a option) (f : 'a -> 'b option) : 'b option =
|
||||||
|
match x with
|
||||||
|
| None -> None
|
||||||
|
| Some a -> f a
|
||||||
|
|
||||||
|
let ( >>= ) = bind
|
||||||
|
|
||||||
|
let binary_operator (x : 'a option) (y : 'b option) (f : 'a -> 'b -> 'c) : 'c option =
|
||||||
|
x >>= (fun a -> y >>= (fun b -> ~= (f a b)))
|
||||||
|
|
||||||
|
let map (x : 'a option) (f : 'a -> 'b) : 'b option =
|
||||||
|
x >>= (fun a -> ~= (f a))
|
||||||
|
|
||||||
|
let compose (f : 'a -> 'b option) (g : 'b -> 'c option) : 'a -> 'c option =
|
||||||
|
(fun x -> f x >>= g)
|
||||||
|
|
||||||
|
let ( >=> ) = compose
|
23
lib/option.mli
Normal file
23
lib/option.mli
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
(* Monadic return for option type. Trivially boxes the variable of type 'a into a 'a option by applying the Some constructor. *)
|
||||||
|
val return : 'a -> 'a option
|
||||||
|
|
||||||
|
(* Monadic return for option type. Trivially boxes the variable of type 'a into a 'a option by applying the Some constructor. *)
|
||||||
|
val ( ~= ) : 'a -> 'a option
|
||||||
|
|
||||||
|
(* Monadic bind for option type. Passes the 'a stored within the 'a option through the supplied function. If the first argument is None, the result is None. *)
|
||||||
|
val bind : 'a option -> ('a -> 'b option) -> 'b option
|
||||||
|
|
||||||
|
(* Monadic bind for option type. Passes the 'a stored within the 'a option through the supplied function. If the first argument is None, the result is None. *)
|
||||||
|
val ( >>= ) : 'a option -> ('a -> 'b option) -> 'b option
|
||||||
|
|
||||||
|
(* Binary operator, applied to the variables of type 'a and 'b respectively in the first two arguments. *)
|
||||||
|
val binary_operator : 'a option -> 'b option -> ('a -> 'b -> 'c) -> 'c option
|
||||||
|
|
||||||
|
(* Maps the supplied function to the 'a within the first argument. *)
|
||||||
|
val map : 'a option -> ('a -> 'b) -> 'b option
|
||||||
|
|
||||||
|
(* Monadic function composition. *)
|
||||||
|
val compose : ('a -> 'b option) -> ('b -> 'c option) -> 'a -> 'c option
|
||||||
|
|
||||||
|
(* Monadic function composition. *)
|
||||||
|
val ( >=> ) : ('a -> 'b option) -> ('b -> 'c option) -> 'a -> 'c option
|
@ -1,5 +1,5 @@
|
|||||||
open List
|
open List
|
||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
|
let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
|
||||||
{ qu with front = a :: qu.back }
|
{ qu with front = a :: qu.back }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
(** Adds an element to the back of the queue, returning the new queue. Runs in O(1). *)
|
(** Adds an element to the back of the queue, returning the new queue. Runs in O(1). *)
|
||||||
val enqueue : 'a -> 'a queue -> 'a queue
|
val enqueue : 'a -> 'a queue -> 'a queue
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
open FromStdlib
|
open FromStdlib
|
||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
let pop (st : 'a stack) : 'a option * 'a stack =
|
let pop (st : 'a stack) : 'a option * 'a stack =
|
||||||
match st with
|
match st with
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
(** Removes the top element from the stack, returning a tuple of the new stack, and None if the stack was empty, or Some [x] if [x] was on top of the stack. Popping an empty stack will result in the returned stack also being empty. Runs in O(1). *)
|
(** Removes the top element from the stack, returning a tuple of the new stack, and None if the stack was empty, or Some [x] if [x] was on top of the stack. Popping an empty stack will result in the returned stack also being empty. Runs in O(1). *)
|
||||||
val pop : 'a stack -> 'a option * 'a stack
|
val pop : 'a stack -> 'a option * 'a stack
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
open FromStdlib
|
open FromStdlib
|
||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree =
|
let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree =
|
||||||
Branch (topBranch, tr1 :: tr2 :: [])
|
Branch (topBranch, tr1 :: tr2 :: [])
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
open Types
|
open Exposed
|
||||||
|
|
||||||
(* Combines two trees of the same type, with the specified value at the new top node. Runs in O(1). *)
|
(* Combines two trees of the same type, with the specified value at the new top node. Runs in O(1). *)
|
||||||
val combine : 'a tree -> 'a tree -> 'a -> 'a tree
|
val combine : 'a tree -> 'a tree -> 'a -> 'a tree
|
||||||
|
Loading…
Reference in New Issue
Block a user