Thomas Bagrel & Arnaud Spiwack
A linear λ-calculus for purely functional memory writes
let rec map f = function
| [] -> []
| a::l -> (f a) :: (map f l)
let mapk f l =
let rec mapk k = function
| [] -> k []
| a::l -> map (fun l' -> (f a) :: l') l
in
mapk (fun l' -> l') l
let mapr f l =
let rec rev acc = function
| [] -> acc
| a::l -> rev (a::acc) l
and mapr acc = function
| [] -> rev [] acc
| a::l -> rev_map ((f a) :: acc) l
in
mapr [] l
😱
Solutions?
type 'a mlist =
| Nil
| Cons of 'a * 'a mlist ref
let mapm f =
let rec mapm (h,r) = function
| Nil -> (r := Nil; !h)
| Cons (a, l) -> begin
let r' := ref Nil in
r := (a :: r');
mapm (h, r') !l
end
in
let r := ref Nil in
mapm (r, r)
let[@tail_mod_cons]
rec map f = function
| [] -> []
| a::l -> (f a) :: (map f l)
let mapm f =
let rec mapm (h,r) = function
| Nil -> (r := Nil; !h)
| Cons (a, l) -> begin
let r' := ref [] in
r := (a :: r');
mapm (h, r') !l
end
in
let r := ref [] in
mapm (r, r)
compiler
magic
let mapm f =
let rec mapm (h,r) = function
| Nil -> (r := Nil; !h)
| Cons (a, l) -> begin
let r' := ref Nil in
r := (a :: r');
mapm (h, r') !l
end
in
let r := ref Nil in
mapm (r, r)
interp
let mapk f l =
let rec mapk k = function
| [] -> k []
| a::l -> map (fun l' -> (f a) :: l') l
in
mapk (fun l' -> l') l
Linear
Linear
no pattern-match
= Ampar b (Dest a)
When you evaluate
then you evaluate
But what if you put the argument in a Dest and make it 🪄 disappear?
https://slides.com/aspiwack/oopsla2025
https://www.tweag.io/blog/tags/linear-types/
https://dl.acm.org/doi/abs/10.1145/3720423
Only semiring operations
let outer :: Ampar (Dest ()) ()
outer = (newAmpar tok1) `updWith` \(dd :: Dest (Dest ())) →
let inner :: Ampar () ()
inner = (newAmpar tok2) `updWith` \(d :: Dest ()) →
dd &fillLeaf d
in fromAmpar' inner
in fromAmpar' outer