We are setting out for Polar
We are moving out on an expedition to Polar: a statically typed language that compiles to JavaScript, built so that the code you write tells you the truth about what it does. The summit is a language you can trust for a whole product. Today we leave the harbor.
Era one: Icebreaker
Every expedition is made of stages, and ours has eras. The first is Icebreaker. An icebreaker doesn't reach the pole. It goes first, cuts a channel through the ice, and makes the way passable for everyone behind it.
That is the work of the 0.x versions. Icebreaker is our basecamp before the mountain: a compiler, a formatter, a standard library, a package system and a real web framework, all pitched on solid ground. Nothing here is the summit. It is where we gather the gear, test the ropes and learn the weather, before the climb to 1.0.
It is early, and the language will change. That is what a first era is for. Version 0.1.0, the first Icebreaker release, is out today.
What we are carrying
Polar lets you write programs for Node and the browser with a type checker that catches mistakes before your code runs. JavaScript is everywhere, and TypeScript made large codebases bearable. But some questions are still answered only by reading code. Does this function touch the network? Will this record have the field I need? Can this module run in the browser? Polar puts the answers in the types.
Records that fit any shape
A function can ask for just the fields it reads, and accept any record that has them. Polar's records are row-polymorphic, so there is no need to declare an interface for every combination. Variants and pattern matching come with exhaustiveness checks, so adding a case shows you every place that needs to handle it.
Effects in the type
An effect is anything a function does besides computing a value: reading the clock, writing to the DOM, talking to a database. In Polar, a function's signature says which ones it uses:
stamp(label: String) -> String / {Clock} {
"#{label} at #{Clock.now()}"
}
Read / {Clock} as "uses the Clock". A function written
without a / {…} is pure, and the compiler checks it in both
directions. A pure function can't sneak in an effect, and a function
can't use one it didn't declare. That makes code easier to test and
easier to move around.
Hosts
Effects live on hosts, such as Browser and
Node. One program can target both. Polar works out where
each function can run, and writes one bundle per host.
Plain JavaScript out
The output is readable ES modules, with source maps and
.d.ts files, so it fits into existing projects. Polar also
calls into JavaScript, so you can use the packages you already know.
First steps
module Main
hosts
Node
functions
main() {
Log.info("Hello from Polar")
}
exports
main
What Icebreaker ships in 0.1.0
-
A CLI with
run,check,build,fmt,init,testandrepl - Projects and packages through
polar.toml - A formatter that keeps your comments, and a VS Code grammar
-
A standard library:
List,Map,Option,Result,Json,Fs,Path,Process,Time,Regex,Crypto,Urland more - Zones, including plugins written in Rust that generate code, which then goes through the same type checker as yours
Every expedition needs a ticket
No one boards without one. Ours is Ticket, a Rails-shaped web framework written in Polar, for Polar projects. It is both the pass for your own journey and the proof that the language can carry real weight. Read about Ticket.
Join the crew
$ curl -fsSL https://polar-lang.vercel.app/install.sh | sh
$ polar --version
You need Node.js to run the code Polar writes. Start with the docs, and tell us what you find out there. Polar is MIT licensed, and issues, ideas and bug reports are welcome on GitHub.
See you on the ice.