

A statically typed functional language
for the Erlang VM
Leandro
staff software engineer


goals
- An ML
- Expressive and sound type-system
- Embraces Erlang and OTP Patterns:
- Functional
- Immutable Data
- Type-Safe Concurrency
- Leverage the Ecosystem:
- Zero-cost Interop with other BEAM languages
- Free and Open Source
- Batteries Included

why an OCaml?
- Pragmatic, sound, proven type-system
-
Small core functional language
- Caramel has been mainly a solo effort
- Good scaling properties
- Functors for type-safe code reuse
- Great compilation times
- Type-safe macro support
- Extensible compiler design
- Elegant syntax

why the Erlang VM?
- Most scalable runtime for functional languages
- Supports massive concurrency & parallelism
- Optimized for low latencies
- Designed for reliability
- Reliability by embracing failure
- Supervision patterns
(think built-in Kubernetes)
- New support for JIT compilation
- A good compilation target platform
(think Elixir, Gleam, Clojerl, Purerl, LFE)

why a sound type system?
- Rule out a large number of errors
- Make illegal states unrepresentable
- Put domain constraints at compile-time
- Makes fearless refactoring easier
- Better autocomplete and developer experience
- Look at what TypeScript did for JS
- Look at what IntelliJ does for Java
- "Typing by convention" is not good enough

why not just write OCaml?
- OCaml runtime is still single threaded
but multi-core is coming soon - Concurrency story:
- cooperative scheduling of promises
on a single thread - IPC-style concurrency
- cooperative scheduling of promises
- OCaml Community is very strong but
rather small compared to e.g Elixir - OCaml Libraries are normally excellent but
rather few compared to Erlang / Elixir

Caramel is an OCaml Dialect
- No mutability, No Object Oriented System
- Statically Typed with Algebraic Data Types
- Tuples, Records
- Variants, Polymorphic Variants
- GADTs
- Full Hindley-Milner Type Inference
- Chances are you'll never *have*
to annotate your code
- Chances are you'll never *have*
- Structurally typed modules
- Lightweight FFI syntax
- Type-safe macros (ppx)


status
Latest version is v0.1, so everything is still a WIP!
- Language Features
- Tooling
- Standard Library
- Documentation & Manual


language
- Lists and Tuples
- Binary Strings
- Arbitrary Precision Integers
- Side-effects, not pure

let rec fib_aux n b a =
if n <= 0 then a
else fib_aux (n-1) (a+b) b
let fib n = fib_aux n 1 0
let main _ =
let fib_nth = [
(10, fib 10);
(1000, fib 1000);
(100000, fib 10000)
]
in Io.format "~p\n" [numbers]

language
- Records and Variants
- Opaque/Abstract Types
- Type-directed pattern matching
with exhaustiveness checks - Type-inference finds out
that handle_action takes a
value of type action based on
pattern matching

(* action can be one of these 2 *)
type action = Login | Logout
(* this is opaque and can't be inspected! *)
type id
(* session must have both of these fields *)
type session = {
logged_in_at: DateTime.t;
user_id: id;
}
let handle_action next state =
match next with
| Login -> (* begin session *)
| Logout -> (* end session *)

language
- Flexible module system
- Partial application and currying
- Tail-call optimization
- Functions with
- named arguments
- pattern matching
- default arguments

module Hello = struct
(* print a name! *)
let say ?(name="Joe") =
Io.format "Hello, ~p!\n" [name]
end
let rec run ~args:(name :: args) =
Hello.say ~name;
run ~args
let main () =
un ~args:["Joe";"Robert";"Mike"]

language
Zero-cost Interop

module Logger = struct
external info : string -> unit = ""
end
let main () = info "hello world"
-module(presentation).
-export([main/0]).
% Calls the actual logger module directly!
main() -> logger:info(<<"hello world">>).

tooling
-
Single binary with no external dependencies
(makes it super easy to bootstrap) - Code formatter built-in
- Coming soon:
- Language server built-in
- Documentation generator built-in
- Type-safe language extension preprocessor
(think embedded GraphQL syntax compiled to type-safe modules and types)
- WIP:
- plugins for rebar3 and mix
- vs-code extension


stdlib
- Current library is a sketch, modeled after the Erlang Stdlib
- Next standard library being designed inspired by Rust, OCaml, and Golang
- Focus on reusing high quality Erlang/Elixir libraries
- Focus on type-safety and developer ergonomics
- Batteries included!
- Core, Async, Collections, Num
- OS, FileSystem, Net, Crypto,
- Common serde (json, toml, yaml, s-expr)
- Typed OTP, Agents


manual
- Introduction to the Language
- Getting Started & Installation
- Guides for Common Tasks
- Calling Erlang/Elixir libs from Caramel
- Calling Caramel code from Erlang/Elixir
- Using with rebar3 or mix
- References
- CLI tool
- Language features
- Standard Library
- How to Contribute
- Building from Source
- Architecture


future
- 2021 goal is to sort of end the year being able
to write the core of a Phoenix app in Caramel 🌟
- There's tons of work to be done across the board
we're still scoping the breadth of it 🗺
- Now 12 supporters on Github Sponsors 🙌🏽
All goes straight into helping Caramel succeed
First goal is underway! 🚀
- Starting monthly meetings with 2 contributors
Primarily communicating on Discord, join us! 📅


thank you!

Caramel: bringing an OCaml to the Erlang VM
By Leandro Ostera
Caramel: bringing an OCaml to the Erlang VM
Here I present Caramel v0.1, answering several common questions like why an OCaml, why on the Erlang VM, why a sound type system, and how is Caramel an OCaml. We'll also go over the status of Caramel v0.1, including language and tooling features, and what's ahead in the roadmap.
- 917