A friendly programming language from the future
Go to file
Paul Chiusano 3c396c5d92 Fix #1388
After fixing this, some serialization round trip tests started failing. This ended up being due to the Eq instance for ABT being busted due to its use of rename, which has a subtle variable capture bug that @dolio spotted a while ago https://github.com/unisonweb/unison/issues/1277 #1277 needs a proper fix but in the meantime, I've tweaked the Eq instance to be a bit more efficient and also avoid the #1277 bug in this particular case.
2020-03-31 19:06:18 -04:00
.github Update pull_request_template.md 2020-03-12 15:22:42 -04:00
contrib Move cabal.project to contrib/ 2020-02-04 08:27:16 -05:00
deps This calls for a commit 2018-11-07 16:38:04 -05:00
docs fixed typo 2019-11-01 18:10:43 -07:00
editor-support Add doc blocks to vim syntax 2020-03-06 15:06:33 -05:00
parser-typechecker Fix #1388 2020-03-31 19:06:18 -04:00
scripts Fix scripts/unisonloop.sh. 2019-10-01 20:36:01 +02:00
unison-core Fix #1388 2020-03-31 19:06:18 -04:00
unison-src add failing transcript 2020-03-23 19:09:01 -04:00
yaks easytest.pending runs hidden tests and reports accordingly 2020-03-26 19:15:19 +00:00
.gitignore ignore all .unison stuff in the build dir 2020-02-20 08:26:02 -05:00
.gitmodules add ANSI patched haskeline as a submodule 2019-03-18 14:29:09 -04:00
.mergify.yml have mergify bot remote "ready-to-merge" label when merging 2020-02-04 11:39:28 -05:00
.travis.yml Add 'delete' command, which combines 'delete.term' and 'delete.type' 2019-12-08 17:29:47 -05:00
config added dev notes document, updated logging defaults 2016-10-06 13:11:38 -04:00
CONTRIBUTORS.markdown Adding myself to CONTRIBUTORS.markdown 2020-03-07 23:07:50 +01:00
development.markdown Move cabal.project to contrib/ 2020-02-04 08:27:16 -05:00
LICENSE This calls for a commit 2018-11-07 16:38:04 -05:00
README.md fixed small error 2019-10-24 21:44:24 +02:00
stack.yaml update Shellmet, hide most git commands 2020-03-28 12:49:02 -04:00

The Unison language

Build Status

Unison is a new programming language, currently under active development. It's a modern, statically-typed purely functional language, similar to Haskell, but with a unique ability to describe entire distributed systems with a single program. Here's a simple example:

-- comments start with `--`
-- alice : Node, bob : Node

x = factorial 6
Remote.transfer alice
y = foo x -- happens on `alice` node
Remote.transfer bob
bar x y -- happens on `bob` node

The Remote.transfer function introduces a "remote effect", where computation may proceed on multiple Unison nodes:

  • The Remote.transfer alice transfers control of the computation to the alice node.
  • The foo x call happens on the alice node.
  • At each transfer, any required definitions (such as foo and x) will be dynamically deployed to the alice node and cached for future use.
  • The Remote.transfer bob transfers control of the rest of the computation to the bob node.
  • The bar x y computation happens on the bob node. Again, any needed definitions (bar, x, and y) will be dynamically deployed to the bob node.

This dynamic transfer / deployment of arbitrary computations is possible because definitions in Unison are identified by a cryptographic hash of their content, including the hashes of all dependencies (the hash is also "nameless" as it isn't affected by naming of variables). To transfer a computation, we send it to the recipient, and the recipient checks to see if the computation references any unknown hashes. Any unknown hashes are synced to the recipient before the transfer completes and the computation proceeds.

If you'd like to learn more about the project, the talk How to write a search engine in 15 lines of code has more of an introduction to the language. For a more complete overview of the syntax look at the unison language reference.

Since Unison isn't terribly useful in its current form, the rest of this README will focus on stuff that will be of interest for potential contributors, namely, how to build the code, and a brief tour of the (fairly small but action-packed) codebase. If you're just interested in the project and want to follow along with the progress, unisonweb.org is the place to go, or you can also say hello or lurk in the Slack chat.

Still here? All right then! Let's get to it.

A brief code tour

First, clone unison with --recursive: git clone --recursive https://github.com/unisonweb/unison.git

Next, a bit of orientation. Here's the directory structure:

  • editor-support/ includes some very basic and probably incomplete text edit support (read: syntax highlighting)
  • yaks/ has subprojects for various utilities not specific to Unison (the result of "yak-shaving"). Once mature, each of these might be moved to independent projects and published on Hackage.
  • parser-typechecker/ has the meat: the Unison syntax tree, parser, typechecker, and runtime. Depends on yaks/

Building using Stack

If these instructions don't work for you or are incomplete, please file an issue.

The build uses Stack. If you don't already have it installed, follow the install instructions for your platform. (Hint: brew update && brew install stack)

$ git clone --recursive https://github.com/unisonweb/unison.git
$ cd unison
$ stack --version # we'll want to know this version if you run into trouble
$ stack build && stack exec tests && stack exec unison

Note: If you get this error:

Stack looks for packages in the directories configured in the 'packages' and 'extra-deps' fields defined in your stack.yaml
The current entry points to <root>/yaks/haskeline/ but no .cabal or package.yaml file could be found there.

then your local git repo is older than the haskeline submodule dependency; use this to get it:

git submodule init
git submodule update

See development.markdown for a list of build commands you'll likely use during development.

A brief tour of the Haskell code

In the parser-typechecker/ project:

  • Unison.Term and Unison.Type have the syntax trees for terms and types. In both Term and Type, the same pattern is used. Each defines a 'base functor' type, F a, which is nonrecursive, and the actual thing we use is an abstract binding tree over this base functor, an ABT F. ABT (for 'abstract binding tree') is defined in Unison.ABT. If you aren't familiar with abstract binding trees, here is a nice blog post explaining one formulation of the idea, which inspired the Unison.ABT module. A lot of operations on terms and types just delegate to generic ABT operations.
  • Unison.Parsers has the main entry point for the parser.
  • Unison.Typechecker.Context is the implementation of the typechecker, and Unison.Typechecker has the "public interface to the typechecker" and some convenience functions. There isn't a lot of code here (about 700 LOC presently), since the typechecking algorithm is pretty simple. Unlike a unification-based typechecker, where the typechecking state is an unordered bag of unification constraints and higher-rank polymorphism is usually bolted on awkwardly later, Dunfield and Krishnaswami's algorithm keeps the typechecking state as a nicely tidy ordered context, represented as a regular list manipulated in a stack-like fashion, and the algorithm handles higher-rank polymorphism very cleanly. They've also extended this work to include features like GADTs, though this new algorithm hasn't been incorporated into Unison yet.