option monad, and some design changes

This commit is contained in:
2021-12-19 08:08:10 +11:00
committed by aaron-jack-manning
parent 1c94d51334
commit de837bbf3b
17 changed files with 82 additions and 33 deletions

View File

@ -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)

View File

@ -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

View File

@ -1,5 +0,0 @@
let id (x : 'a) = x
let ( >> ) f g x = g (f x)
let ( << ) g f x = g (f x)

View File

@ -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

View File

@ -1,5 +1,5 @@
open FromStdlib
open Types
open Exposed
let empty : 'a list = []

View File

@ -1,4 +1,4 @@
open Types
open Exposed
(** The empty list *)
val empty : 'a list

View File

@ -1,3 +1,3 @@
open FromStdlib open Types
open FromStdlib open Exposed
let _ = printf "Hello, World\n"

View File

@ -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
View 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
View 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

View File

@ -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 }

View File

@ -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

View File

@ -1,5 +1,5 @@
open FromStdlib
open Types
open Exposed
let pop (st : 'a stack) : 'a option * 'a stack =
match st with

View File

@ -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

View File

@ -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 :: [])

View File

@ -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