Starting with a fragmentary understanding of ocaml I build an ocaml version of the division algebras. I keep the Scheme pattern where an algebra is a value bound to an identifier but in OCaml such values are called ‘modules’, are static and completed upon compilation. The mathematical ideas are in the Scheme development and not here. An algebra is roughly what an ocaml ‘module’ is for. Module names (as in “ Xx ” from “ module Xx = struct end;; ”) are in a special static space however. The Scheme version creates the new types dynamically whereas Ocaml can create them only at compile time but that is not a practical problem in the case at hand. I would like to see other applications of the Ocaml functor.

I try to do reals as reals from the division algebras.

(define reals (list (lambda (x) x) rr 0 zero? 1 + - * (lambda (x) (/ x))))

rr

module Reals = struct type kind = float let conj x : float = x let zero = 0. let one = 1. let zeroQ x = x = 0. let (+) = (+.) let (-) = (-.) let ( * ) = ( *.) let inv x = 1. /. x end

module Reals : sig type kind = float val zero : float val conj : float -> float val one : float val zeroQ : float -> bool val ( + ) : float -> float -> float val ( - ) : float -> float -> float val ( * ) : float -> float -> float val inv : float -> float end

module Reals : sig type kind val conj : kind -> kind val zero : kind val one : kind val zeroQ : kind -> bool val (+) : kind -> kind -> kind val (-) : kind -> kind -> kind val ( * ) : kind -> kind -> kind val inv : kind -> kind val str : kind -> string end = struct type kind = float let zero = 0. let conj x = x let one = 1. let zeroQ x = x = 0. let (+) = (+.) let (-) = (-.) let ( * ) = ( *.) let inv x = 1. /. x let str = string_of_float end

Reals.str (Reals.(+) Reals.one Reals.one);; - : string = "2."

DivAlgebra

module type DivAlgebra = sig type kind val conj : kind -> kind val zero : kind val one : kind val zeroQ : kind -> bool val (+) : kind -> kind -> kind val (-) : kind -> kind -> kind val ( * ) : kind -> kind -> kind val inv : kind -> kind val str : kind -> string end;;

Reals

BareReals

module BareReals = struct type kind = float let conj x = x let zero = 0. let one = 1. let zeroQ x = x = 0. let (+) = (+.) let (-) = (-.) let ( * ) = ( *.) let inv x = 1. /. x let str = string_of_float end;;

Reals

module Reals = (BareReals : DivAlgebra);;

DivAlgebra

DivAlgebra

module G = functor (Alg: DivAlgebra) -> struct type kind = {r: Alg.kind; i: Alg.kind} let conj x = {r = Alg.conj x.r; i = Alg.(-) Alg.zero x.i} let zero = {r = Alg.zero; i = Alg.zero} let one = {r = Alg.one; i = Alg.zero} let zeroQ x = Alg.zeroQ x.r & Alg.zeroQ x.i let (+) x y = {r = Alg.(+) x.r y.r; i = Alg.(+) x.i y.i} let (-) x y = {r = Alg.(-) x.r y.r; i = Alg.(-) x.i y.i} let ( * ) x y = {r = Alg.(-) (Alg.( * ) x.r y.r) (Alg.( * ) (Alg.conj x.i) y.i); i = Alg.(+) (Alg.( * ) x.r y.i) (Alg.( * ) x.i y.r)} let inv x = let d = Alg.inv (Alg.(+) (Alg.( * ) x.r (Alg.conj x.r)) (Alg.( * ) x.i (Alg.conj x.i))) in {r = Alg.( * ) d (Alg.conj x.r); i = Alg.(-) Alg.zero (Alg.( * ) d x.i)} let str x = Alg.str x.r ^ ", " ^ Alg.str x.i end;;

module Complex = G(Reals);;

Complex.str (Complex.(+) Complex.one Complex.one);; - : string = "2., 0."

module Quaternion = G(G(Reals));;

Quaternion.str (Quaternion.(+) Quaternion.one Quaternion.one);; - : string = "2., 0., 0., 0."

module G = functor (Alg: DivAlgebra) -> struct open Alg type kind = {r: Alg.kind; i: Alg.kind} let conj x = {r = conj x.r; i = (-) zero x.i} and zero = {r = zero; i = zero} and one = {r = one; i = zero} and zeroQ x = zeroQ x.r & zeroQ x.i and (+) x y = {r = x.r + y.r; i = x.i + y.i} and (-) x y = {r = x.r - y.r; i = x.i - y.i} and ( * ) x y = {r = x.r * y.r - (conj x.i) * y.i; i = x.r * y.i + x.i * y.r} and inv x = let d = inv (x.r * (conj x.r) + x.i * (conj x.i)) in {r = d * (conj x.r); i = zero - d * x.i} and str x = str x.r ^ ", " ^ str x.i end;;

open Alg

Alg.

Alg.

kind