option monad, and some design changes
This commit is contained in:
@ -10,4 +10,11 @@ type 'a stack =
|
||||
|
||||
type 'a tree =
|
||||
| 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)
|
@ -13,4 +13,13 @@ type 'a stack =
|
||||
(* A purely functional tree with arbitrarily many branches at each node. *)
|
||||
type 'a tree =
|
||||
| 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 Types
|
||||
open Exposed
|
||||
|
||||
let empty : 'a list = []
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
open Types
|
||||
open Exposed
|
||||
|
||||
(** The empty list *)
|
||||
val empty : 'a list
|
||||
|
@ -1,3 +1,3 @@
|
||||
open FromStdlib open Types
|
||||
open FromStdlib open Exposed
|
||||
|
||||
let _ = printf "Hello, World\n"
|
@ -4,14 +4,13 @@ build:
|
||||
ocamlopt -i fromStdlib.ml > fromStdlib.mli
|
||||
ocamlopt -S -O3 -c fromStdlib.mli fromStdlib.ml
|
||||
|
||||
# types for other modules separated to easily expose without module reference in projects
|
||||
ocamlopt -S -O3 -nopervasives -c types.mli types.ml
|
||||
# exposed types and functions, that can be opened module wide
|
||||
ocamlopt -S -O3 -nopervasives -c exposed.mli exposed.ml
|
||||
|
||||
# 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 float.mli float.ml
|
||||
ocamlopt -S -O3 -nopervasives -c float.mli float.ml
|
||||
ocamlopt -S -O3 -nopervasives -c functions.mli functions.ml
|
||||
ocamlopt -S -O3 -nopervasives -c option.mli option.ml
|
||||
ocamlopt -S -O3 -nopervasives -c stack.mli stack.ml
|
||||
ocamlopt -S -O3 -nopervasives -c list.mli list.ml
|
||||
ocamlopt -S -O3 -nopervasives -c map.mli map.ml
|
||||
@ -24,7 +23,7 @@ build:
|
||||
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
|
||||
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:
|
||||
|
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 Types
|
||||
open Exposed
|
||||
|
||||
let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
|
||||
{ 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). *)
|
||||
val enqueue : 'a -> 'a queue -> 'a queue
|
||||
|
@ -1,5 +1,5 @@
|
||||
open FromStdlib
|
||||
open Types
|
||||
open Exposed
|
||||
|
||||
let pop (st : 'a stack) : 'a option * 'a stack =
|
||||
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). *)
|
||||
val pop : 'a stack -> 'a option * 'a stack
|
||||
|
@ -1,5 +1,5 @@
|
||||
open FromStdlib
|
||||
open Types
|
||||
open Exposed
|
||||
|
||||
let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree =
|
||||
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). *)
|
||||
val combine : 'a tree -> 'a tree -> 'a -> 'a tree
|
||||
|
Reference in New Issue
Block a user