Total functional sublanguage typesystem

A type is either a tagged product

{on_1: type_1 , .. , on_n: type_n}

or a tagged sum

<in_1(type_1) | .. | in_n(type_n)>

Untagged product and sum types just have the default tags 'on_i' and 'in_i' filled in.
The tags are turned into functions, destructors with '.' or constructors with '&'.

let eitan: {name: string, age: int} = {name: "Eitan" , age: 33}
.name(eitan) = "Eitan"
.age(eitan) = 33
let id: <ssn(int) | email(string)> = &ssn(123456789)

We also need to be able to exhaustively match branches of sum types

let num: int = <ssn(x) -> x | email(addr) -> length(addr)>(id)

The only thing still needed to define ADTs are type aliases

type human = {name: string, age: int}
eitan: human = {name: "Eitan", age: 33}

We also want a higher kinded type alias

type list(x) = <empty_list() | cons(x,list(x))>
let mylist: list(int) = &cons(1,&cons(2,&cons(3,&empty_list())))

We can define a datatype for algebraic type syntax within Haskell as

data AlgebraicType
  = Primitive PrimitiveType
  | Product [(String,AlgebraicType)]
  | Sum [(String,AlgebraicType)]
  | TypeAlias String AlgebraicType
  | HigherTypeAlias String AlgebraicType AlgebraicType
data RhoType
= Algebraic AlgebraicType
  | Process AlgebraicType
| Function AlgebraicType AlgebraicType

Next, we want support a syntax sugar for various "loops".

Functor, Monad, Foldable, Traversable

A functor will mean a higher kinded type alias with a 'map' function.

type list(x) = <empty_list() | cons({head: x,tail: list(x)})>

map(f: x -> y, as: list(x)): list(y) =
  < empty_list() -> empty_list()
| cons({head: b,tail: bs}) -> cons({head: f(b),tail: each(b <- bs) f})
>(as)

An monad will mean a functor also with a 'yield', 'flatten' and 'flat_map' function.


yield(a: x): list(x) = &cons({head: a, tail: &empty_list()})

append(as: list(x), bs: list(x)) =
< empty_list() -> bs
, cons({head: c, tail: cs}) -> cons({head: c, tail: append(cs, bs)})
>(as)

flatten(ass: list(list(x)): list(x) =
< empty_list() -> empty_list()
| cons({head: bs, tail: bss}) -> append(bs, join(bss))
> ass

flat_map(f: x -> list(y), as: list(x)) = flatten(map(f, as))

A traversable will mean a functor also with a 'traverse' and 'sequence' function
...

************
Relevant papers:
https://tech.labs.oliverwyman.com/downloads/ex_nihilo_logic.pdf
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.3.9964&rep=rep1&type=ps