2025-08-01

referential math notation (rmn) specification

an ascii plaintext math notation

identifiers, types, and function application

use lowercase ascii identifiers with underscores. type annotations follow the form:

function_name(arg1: type1, arg2: type2): return_type

all operations use explicit prefix calls:

contains(set, element)
compose(f, g)
product(type_a, type_b)

struct and module declarations

type group:
  id: string
  start_time: time
  duration: time
module potential_mounting:
  function referenced_groups(p: potential): list = ...
  function root_group(p: potential): group = ...

functions

function root_group(p: potential): group =
  find_shallowest(mounted_groups(p))

functions are total and context-free. no overloading. no implicit dependencies.

definitions and scoping

group related functions in bundled blocks:

potential_analysis:
  function root_group(p: potential): group = ...
  function evaluate_window(p: potential): (time, duration) =
    let g = root_group(p)
    in (g.start_time, g.duration)

allow lexical scoping with let, match, and block structure.

quantification and iteration

replace symbolic quantifiers with iteration:

for g in all_groups:
  for p in referenced_potentials(g):
    evaluate_window(p, g)

use existential forms as needed:

for epsilon in positive_reals:
  exists delta in positive_reals:
    for x in reals:
      if abs(x - c) < delta:
        abs(f(x) - l) < epsilon

indexing and summation

use explicit index binding:

sum(i: 1..n, a[i][j] * b[j][k])

define arrays as typed functions:

a: function(i: int, j: int): real

function composition and pipelines

write composition and dataflow explicitly:

compose(g, f)(x) = g(f(x))
pipe(x, f, g) = g(f(x))

always declare domain and codomain:

f: function(x: a): b
g: function(y: b): c

avoiding point-free style

avoid combinators and implicit flows. use named expressions:

delta(x) = (x, x)
pair(x) = (x, f(x))

operator precedence

enforce full parenthesization:

sub(add(1, div(mul(2, pow(c, d)), e)), f)

optional infix dsls must define evaluation precedence explicitly.

set comprehension

replace set-builder notation with functional constructs:

filter(x in reals, x*x < 2)

define derived sets explicitly:

def bounded_square_root_domain(): set =
  filter(x in reals, x*x < 2)

ranges and sequences

avoid .... use explicit ranges and generators:

sum(i: 1..n, i)
sequence(n: int): list = map(i: 1..n, i)

algebraic data types

support tagged sum types using variant syntax:

type expr =
  | number(value: real)
  | variable(name: string)
  | binary(op: operator, left: expr, right: expr)

anonymous functions

allow inline function expressions:

map(list, function(x): x * x)

preconditions and partial domains

define domains of partial functions explicitly:

function log(x: real): real
  precondition: x > 0

or use guarded total forms:

function log(x: real): real?
  if x > 0 then return natural_log(x)

logic and proof annotations

represent predicates as first-class functions:

predicate is_prime(n: int): bool

annotate proofs as data when needed:

proof: exists p in primes: divides(p, n)

error and result types

support result-returning functions for safe operations:

function safe_sqrt(x: real): result

symbol definitions and traits

define all functions explicitly:

phi: function(x: group_elem): group_elem = ...

use traits where needed:

trait group_homomorphism:
  function map(x: group_elem): group_elem

notation expansion

allow symbolic shorthands through scoped definitions:

namespace innerproductspace:
  function inner(x: vector, y: vector): scalar
  notation: "⟨x, y⟩" maps to inner(x, y)

all notation must be expandable to referential form.

additional constructs

partial functions with guards:

function safe_div(x: real, y: real): real?
  if y ≠ 0 then return x / y

first-class predicates:

is_even: function(n: int): bool = mod(n, 2) == 0

pattern matching on records:

match g as group:
  id = g.id

tagged functions with traits:

φ: map g -> h where φ is group_homomorphism

examples

here are a few examples from traditional mathematics that are ideal for showcasing the clarity and compositional benefits of rmn. each is representative of a different domain and difficult to follow without prior symbolic fluency.

epsilon-delta definition of limit (analysis)

traditional:

∀ε > 0 ∃δ > 0 ∀x (0 < |x - c| < δ ⇒ |f(x) - l| < ε)

rmn:

for epsilon in positive_reals:
  exists delta in positive_reals:
    for x in reals:
      if 0 < abs(x - c) and abs(x - c) < delta:
        abs(f(x) - l) < epsilon

functoriality and composition (category theory)

traditional:

f(g ∘ f) = f(g) ∘ f(f)

rmn:

compose(f(g), f(f)) = f(compose(g, f))

matrix multiplication (linear algebra)

traditional:

c_{ik} = ∑_{j=1}^{n} a_{ij} b_{jk}

rmn:

c(i, k) = sum(j: 1..n, a(i, j) * b(j, k))

set-builder and predicate logic (set theory / logic)

traditional:

{x ∈ ℕ | ∃y ∈ ℕ, y² = x}

rmn:

filter(x in naturals, exists y in naturals: y * y = x)

defining an inner product space (linear algebra / functional analysis)

traditional:

⟨x, y⟩ = ∑_{i=1}^{n} xᵢ yᵢ

rmn:

inner(x: vector, y: vector): scalar =
  sum(i: 1..n, x(i) * y(i))

pointwise function equality (set functions / logic)

traditional:

f = g ⇔ ∀x ∈ a, f(x) = g(x)

rmn:

functions_equal(f, g, domain) =
  for x in domain:
    f(x) = g(x)

canonical translation examples

∀x ∈ a: p(x)                         -> for x in a: p(x)
∃x ∈ a: p(x)                         -> exists x in a: p(x)
f ∘ g                                -> compose(f, g)
x ∈ a                                -> contains(a, x)
a × b                                -> product(a, b)
{ x ∈ ℝ | x² < 2 }                   -> filter(x in reals, x * x < 2)
1 + 2 + ... + n                      -> sum(i: 1..n, i)
∑_{i=1}^{n} f(i)                     -> sum(i: 1..n, f(i))
a[i][j]                              -> a(i, j)
let f: g -> h                         -> f: function(x: g): h
⟨x, y⟩                               -> inner(x, y)
id × f                               -> product(id, f)
δ(x)                                 -> (x, x)
(x, f(x))                            -> pair(x) = (x, f(x))
φ is a group homomorphism            -> φ: function(x: group_elem): group_elem satisfies group_homomorphism
f: a -> b, g: b -> c, h = g ∘ f        -> f: function(x: a): b, g: function(y: b): c, h(x) = compose(g, f)(x)
x ∈ dom(f)                           -> contains(domain(f), x)
∀ε > 0 ∃δ > 0 ∀x |x−c|<δ ⇒ ...       -> for epsilon in positive_reals: exists delta in positive_reals: for x in reals: if abs(x - c) < delta: ...
log(x), x > 0                        -> function log(x: real): real? if x > 0 then return natural_log(x)
{1, 2, ..., n}                       -> range(1, n)
λx. f(x)                             -> function(x): f(x)
~ x                                  -> not(x)
a ∩ b                                -> intersection(a, b)
a ∪ b                                -> union(a, b)
a ⊆ b                                -> subset(a, b)
a ∖ b                                -> difference(a, b)
true                                 -> true
false                                -> false
¬p ∨ q                               -> or(not(p), q)
p ∧ q                                -> and(p, q)
p ⇒ q                                -> implies(p, q)
p ⇔ q                                -> iff(p, q)
min(x₁, ..., xₙ)                     -> reduce(min, [x1, ..., xn])
max(x₁, ..., xₙ)                     -> reduce(max, [x1, ..., xn])
lim_{x->a} f(x)                       -> limit(f, x -> a)
d/dx f(x)                            -> derivative(f, x)
∫₀ⁿ f(x) dx                          -> integral(f, x, lower=0, upper=n)
a = b = c                            -> a = b and b = c
a ≠ b                                -> not(a = b)
if x ∈ a then y ∈ b                 -> if contains(a, x): contains(b, y)

desugaring table

this table ensures that all high-level rmn constructs are syntactic sugar over a minimal, core language with function application, binding, types, and blocks.

implicit ranges

sum(i: 1..n, expr)

->

sum(i in range(1, n), expr)

pipeline

pipe(x, f, g)

->

g(f(x))

function composition

compose(f, g)(x)

->

f(g(x))

array notation

a[i][j]

->

a(i, j)

anonymous function (lambda)

function(x): expr

->

lambda_expr(param = x, body = expr)

set filtering

filter(x in domain, condition)

->

filter(domain, function(x): condition)

optional types

real?

->

optional

precondition

function f(x: t): u
  precondition: p

->

function f(x: t): u?
  if p then return 

record match

match r as t:
  f1 = ...
  f2 = ...

->

let f1 = r.f1
let f2 = r.f2

shorthand trait tagging

φ: map g -> h where φ is group_homomorphism

->

φ: function(x: group_elem): group_elem
  satisfies group_homomorphism

ebnf grammar sketch

program          ::= (definition | type_decl | module_decl)*
definition       ::= "function" identifier "(" param_list ")" ":" type ("=" expr | block)
                  | "predicate" identifier "(" param_list ")" ":" "bool"
                  | "proof" ":" expr
type_decl        ::= "type" identifier ":" field_list
                  | "type" identifier "=" variant_list
module_decl      ::= "module" identifier ":" block
variant_list     ::= variant ("|" variant)*
variant          ::= identifier "(" field_list ")"
field_list       ::= field ("," field)*
field            ::= identifier ":" type
param_list       ::= param ("," param)*
param            ::= identifier ":" type
block            ::= indent (definition | expr)* dedent
expr             ::= call_expr
                  | if_expr
                  | match_expr
                  | lambda_expr
                  | literal
                  | identifier
call_expr        ::= identifier "(" arg_list ")"
arg_list         ::= expr ("," expr)*
if_expr          ::= "if" expr "then" expr ("else" expr)?
match_expr       ::= "match" identifier "as" identifier ":" field_list
lambda_expr      ::= "function(" identifier ")" ":" expr
literal          ::= number | string | boolean
type             ::= identifier | type "?" | "list<" type ">" | "set<" type ">" | "result<" type "," type ">"

note: indentation-based syntax is assumed. sugar constructs (like sum(i: 1..n, ...)) must desugar into core forms.