A set of curated examples to show ATS' capacities for functional and imperative programming, wherein we sum the numbers \(1..n\) many times:
Recursion
fun sum {m:nat} .<m>. (x : int(m)) :<> int =
case+ x of
| 0 => 0
| n =>> x + sum(x - 1)
Recursion + Stack-Allocated Closure
fun sum {m:nat}(x : int(m)) : int =
let
var go = fix@ loop (i : [i:nat] int(i)) : int =>
case+ i of
| 0 => 0
| n =>> i + loop(i - 1)
in
go(x)
end
Recursion + Call-by-Reference
fn sum {m:nat}(x : int(m)) :<!wrt> int =
let
fun loop {n:nat} .<n>. (y : int(n), res : &int? >> int) :<!wrt> void =
case+ y of
| 0 => res := 0
| n =>> (loop(y - 1, res) ; res := res + y)
var res: int
val () = loop(x, res)
in
res
end
C FFI
%{
int sum(int n) {
int i, sum = 0;
for (i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
%}
extern
fn sum(intGte(0)) :<> intGte(0) =
"mac#"
For Loop
fn sum {m:nat}(x : int(m)) :<!wrt> int =
let
var res: int = 0
var i: int
val () = for* { i : nat | i <= m } .<i>. (i : int(i)) =>
(i := x ; i > 0 ; i := i - 1)
(res := res + i)
in
res
end
While Loop
fn sum {m:nat}(x : int(m)) :<!wrt> int =
let
var res: int = 0
var i: int = x
val () = while* { i : nat | i <= m } .<i>. (i : int(i)) =>
(i > 0)
(res := res + i ; i := i - 1)
in
res
end
Recursion + Stack-Allocated Variable
fn sum {m:nat}(x : int(m)) :<!wrt> int =
let
fun loop {n:nat}{l:addr} .<n>. (pf : !int @ l | n : int(n), res : ptr(l)) :<!wrt> void =
case+ n of
| 0 => ()
| n =>> let
val () = !res := !res + n
in
loop(pf | n - 1, res)
end
var ret: int with pf = 0
val () = loop(pf | x, addr@ret)
in
ret
end
Linear Streams
fn sum {m:nat}(x : int(m)) :<!ntm> int =
let
fun build_stream {i:nat} .<i>. (y : int(i)) :<> stream_vt(int) =
case+ y of
| 0 => $ldelay(stream_vt_nil)
| n =>> $ldelay(stream_vt_cons(y, build_stream(y - 1)))
fun fold_stream(xs : stream_vt(int)) :<!ntm> int =
case+ !xs of
| ~stream_vt_nil() => 0
| ~stream_vt_cons (y, ys) => y + fold_stream(ys)
in
fold_stream(build_stream(x))
end
Hylomorphism
datatype list0f(a: t@ype, x: t@ype+) =
| list0_consf of (a, x)
| list0_nilf of ()
abstype functor_type(a: t@ype, x: t@ype+) = ptr
typedef functor(a: t@ype, x: t@ype+) = functor_type(a, x)
extern
fun {a:t@ype}{b:t@ype}{t:t@ype} map (a -<cloref1> b, functor(t,a)) : functor(t, b)
typedef algebra(a: t@ype, x: t@ype) = functor(a, x) -<cloref1> x
typedef coalgebra(a: t@ype, x: t@ype) = x -<cloref1> functor(a, x)
fun {b:t@ype}{a:t@ype}{t:t@ype} hylo(f : algebra(t, b), g : coalgebra(t, a), x : a) : b =
f(map(lam x0 => hylo(f, g, x0), g(x)))
absimpl functor_type(a, x) = list0f(a, x)
implement {a}{b}{t} map (f, x) =
case+ x of
| list0_consf (x, xs) => list0_consf(x, f(xs))
| list0_nilf() => list0_nilf
fn sum (x : intGte(0)) : int =
let
fn alg(xs : list0f(int, int)) : int =
case+ xs of
| list0_consf (x, xs) => x + xs
| list0_nilf() => 0
fn coalg(x : int) : list0f(int, int) =
case+ x of
| 0 => list0_nilf
| x => list0_consf(x, x - 1)
in
hylo(lam x0 => alg(x0), lam x1 => coalg(x1), x)
end