announcements
Jul 14, 2022

Announcing Unison Milestone Release 4

Rúnar Bjarnason

We have just released a major milestone of Unison: version M4, and it's a big one. Here are the details on the most significant changes.

Code hosting on Unison Share

We built our own codebase hosting specifically designed for Unison, as a feature ofUnison Share.

Before now, if you wanted to collaborate on a Unison codebase or share your code with others, you had to do so through binary files managed with Git. When viewing your code on e.g. GitHub, all you saw was a directory with a binary file in it.

This all changes today. You can now push your Unison code directly to Share via the Codebase Manager, and then browse and share it in a beautiful interface, all gloriously hyperlinked.

How to get started with Unison Share

  1. Create a new Share account atshare.unison-lang.org.You can use your GitHub account.
  1. Startucmin your terminal, pointing to your Unison codebase.
  1. Fromucm,issuepush myUsername.public.project mycodewheremycodeis whatever namespace you want to push to Share, andmyUsernameis your Share user name (which is the same as your GitHub user name).

You can now share your code with the world!

Here's a short video of Simon pushing his code:

What will happen to the old Unison Share?

The old Unison Share site is still available for now atshare-prev.unison-lang.org,but it's deprecated. If you have Unison code on the old site, we encourage you to push it to the new Share as described above.

Self-contained namespaces

In past versions of Unison, name resolution was global for your whole codebase. That is, if you used a name likefoo,Unison would look for things namedfooeverywhere in your codebase to figure out what hash you meant.

This had a number of problems:

  1. Name lookup was slow for large codebases.
  2. If you had a lot forks of a namespace, you might end up with ambiguous names, and Unison would insist on overly long fully-qualified names to disambiguate.
  3. Namespaces implicitly depended on each other in a way that was hard to understand. As namespaces evolved separately, you might end up with code referencing hashes that no longer had names. If you pushed a namespace to share, but not its dependencies, you might end up with code on Share with hashes instead of names.

Starting with version M4, Unison's namespaces are self-contained, meaning that name resolution is local to each namespace. This makes the Unison workflow slightly different, but it's a lot easier to understand in the end. Whereas before M4, you could do the following:

  1. Start up UCM.
  2. cdinto a new namespacefoo.
  3. Start coding with everything from your codebase in scope.

Now you do this:

  1. Start up UCM.
  2. cdinto a new namespacefoo.
  3. forkany namespaces you want to use, and put them underfoo.lib.For example,fork .base foo.lib.base.You can even have a namespace in your codebase that serves as a template, andforkthat for each new project.
  4. Start coding with just the namespaces you want to use in scope.

In future releases of Unison, we will add lots of quality-of-life features to make managing your namespaces and projects more ergonomic.

Mutable and immutable arrays

Unison M4 gets some new built-in types representing in-memory arrays:

Arrays allow for efficient memory usage as well as fast random access, splitting, and slicing. What's more, mutable arrays arescopedusing theScopeability, which means mutable memory can't escape the scope in which it was allocated. For example, you cannot have a global mutable array, and the type system enforces this.

Seearraysfor more information on how to use arrays.

A date/time library

There are new builtins for nanosecond-precision system clocks. For example:

  • nowreturns the current time, as anInstant.
  • Clock.monotonicreturns a monotonically increasingtime.Durationthat is guaranteed to never go backwards (which can otherwise happen if the system clock is adjusted).

Thebase.timenamespace contains a number of useful functions and data types for working with time and dates.

Efficient regular expressions for text and binary data

The Base library has a new type,Pattern,which is a regular expression pattern. Ap : Pattern Bytesis a pattern that matchesTextinput, and ap : Pattern Bytesis a pattern that matchesBytesinput.

The["123"]in the above output is a list ofcaptures,and the"abc"is the remainder of the input after thePattern.many patterns.digitsuccessfully matches.

APatternis built up using functions likePattern.many,literal,charRange,and so on, and run with eitherPattern.runorisMatch:

Pattern.run : Pattern a -> a -> Optional ([a], a)
isMatch : Pattern a -> a -> Boolean

For more information on patterns, seePattern.

New keyword: do

Thedokeyword is new syntactic sugar for'let,which introduces an unevaluated block of code. For example, you can now write:

main : '{IO, Exception} ()
main = do
  printLine "Greetings, earthling! 👽🪐"
  printLine "You can still use 'let if you really want."

The pretty-printer usesdowherever it can, so all your existing code is already updated to use this new syntax.

And lots more

Those are the big changes, but there have also been a ton of bugfixes, performance enhancements, and various ergonomic improvements.

Check out the release notes for the full list of changes.

Head to theUnison websitefor download/upgrade instructions.

Do create a Unison Share account and put all your amazing code there.

Enjoy! 🚀