Please log in to watch this conference skillscast.
Unison is a new open source functional programming language based on a simple idea with big implications: every type and definition in the language has a unique cryptographic signature, determined by its content. Instead of a bag of mutable text files, the Unison codebase is a distributed immutable data structure and the signature serves as a global address into this structure. This is the basis for some serious improvements to the developer experience. Unison has no builds, no dependency conflicts in the traditional sense, and it allows for easy dynamic deployment of code in a distributed setting.
Question: So if you have a hashed store of evaluations, does this mean you have timing attacks where you query a store, looking for cache hits to get a handle on exactly what code someone is running?
Answer: I’ll have to think about that one. My initial reaction is that you’d have to have the kind of in-process access to the node such that you could just dump its memory anyway.
Question: Does Unison have FFI? (This is a joke -- in case you're not fully awake yet. But not completely a joke...)
Answer: We don’t have FFI exposed as a programmer facility, but that’s planned.
Question: So I guess that means there’s currently no interop with Haskell?
Answer: There’s no programmer facility for calling arbitrary Haskell code, no
Question: If everything is a hash, won't there inevitably be collisions? Wouldn't it then be possible to accidentally invoke a function that launches nuclear missiles instead of reading a number from a DB?
Answer: The hashes are 512-bit SHA-3, so hash collisions are unimaginably unlikely. If you hashed a billion Unison definitions per second, you could expect your first collision in about 100 trillion years.
I’m sympathetic to the fact that some applications (like missile silos) won’t want to take that kind of risk (although your silo is more likely to be struck by lightning and a meteor at the same time)
Question: If a node always gets the code exactly when called, is there any story around blue-green style deployments? Is there anything for using nodes running on different platforms (operating system, processor architecture, etc)?
Answer: The node could have the code pre-loaded for sure. There will always be some subset of your codebase that’s on every node right from the start. Can you elaborate on blue/green deployments? I’m not familiar with that. Unison runs on a virtual machine written in Haskell, so it can currently run on any architecture that Haskell can target.
Question: Blue/green is where a version of code is deployed without taking the old down and then a swap to point at the new version is performed (dns or otherwise)
Answer: Oh yes, absolutely. Since everything is first-class, you can imagine for example a process listening on a queue for its own definition.
Question: Does this make Unison documentation Turing complete? Do you write tests for your documentation?
Answer: Yes and yes.
Question: You say everything is referenced by hash rather than name, but you're still using names like myConstant and type Nat - so it seems as though there are names associated with these hashes in some way - how does that work?
Answer: Names are a “development-time” thing. They’re only used for two things:
1.Show something nicer than a hash to the programmer when printing code.
2. Reference hashes using something nicer for the programmer than hashes.
The compiled form has only the hashes, and then the hash has a name (or several)
associated with it which we can use to print the code back. When you
update a name, UCM interprets that as meaning “move this name to
the hash of this definition…and create new versions of its dependencies (scoped
to a specific namespace) that reference the new hash, and update their names
So potentially when you
update Unison does a lot of code generation
and moving names to new hashes
Question: Sorry if this is a silly question, but if unison code is like a database and can be exposed on the web, can one expose an api to make a post to a unison server and then mutate the underlying unison program?
Answer: It’s more like a git immutable database - It’s append only. You can create new programs, but you can’t change them
Question: How do names interact though? Names are not immutable
Answer: They are. When you change a name, you create a new namespace and the previous one gets added to its history.
Question: Do I import my dependencies by hash? Or: How do I
"update my dependencies"? E.g. if I use an external function
it will reference it's hash. But when the author of foo changes the code, how do
I get the new version of the code?
Answer: If that author is you, you can have UCM do the update
for you automatically (the
update command does this). If the author
is not you, the author can ship a patch as part of a “release” of the library. A
patch is just a map from old hash to new hash, basically. Currently when you
pull a dependency from e.g. Git, any patch named
patch in its root
gets automatically applied.
Question: Wouldn't it be nice if sensible optimisations /
transformations were applied before hashing, so that if you wrote
traverse in a slightly different way from someone else, unison can
still tell you you just wrote
traverse (again)... is this possible
now? In the roadmap?
Answer: Possible within limits. In general you run into questions of intensional vs intensional equivalence. This is not on the roadmap.
Question: The name lookup system seems to enable ad-hoc polymorphism per function
Answer: Yes! Function names are “polymorphic” in the sense that the type information is used to look up the code for them. Kind of like virtual method tables, innit
Question: Similar to Haskell, could you annotate a definition (to be included in its hash) with rewrite rules to apply to expressions that reference that definition?
Answer: Certainly possible in future!
Question: How do copyleft licenses interact with the unison "store"? If I write something in the strongest copyleft licence I can find, and you write the same function under WTFPL, what happens? Does licence information change the hash of functions?
Answer: You can in principle compute the “transitive license” of any definition, and all the components are there for spitting out a warning if you’re about to use something that introduces a license you don’t want. But we’re not doing anything (and don’t intend to do anything) to enforce licenses. If you write the same definition as somebody else under a different license, we do basically what Github does
Question: When you compute the transitive license, is "incompatible" a valid answer? eg. CDDL and GPLv3
Answer: You could definitely do that. We’re not currently doing anything interesting with licenses, but once we have a Unison API for the codebase you’ll be able to write stuff like this
Question: The thing I'm most curious about is: what's the plan for type-classes? ..or if not type-classes, how is similar abstraction intended to be achieved?
Answer: The plan for type classes is currently to do something very similar to what Scala 3 is doing. Type classes are on the roadmap for a future version, but not something anyone is working on currently to my knowledge.
Question: So in this case pushing one function at a time is the expected workflow? and then test code would be like any other code that lives within the “prod” code? I have a to have a look at how that works… It is such a change of how we play the game currently… It’s a “Software Engineering Platform”… All in one
Answer: You can push as many functions as you like at a time. I
often will write a dozen or so definitions and
add them once I’m
happy. I forgot to show off testing. The normal workflow is to add a watch
test> myTest = … .UCM expects your test to have a
particular type, and it understands that it’s a test. Otherwise it’s just a
Unison definition like any other. The convention I’ve been using is for
foo to have all the tests for
under a namespace
See here for a video of me adding a test:
Question: I'm interested to know what a large codebase refactoring might look like.
Answer: It’s pretty good! For simple refactorings, UCM can just propagate your changes automatically. For more complicated refactorings that introduce type changes and other conflicts, UCM computes an “edit frontier” for you and guides you through pushing that frontier along your dependency chain. See https://www.unisonweb.org/docs/refactoring/
Question: And also code reviews.
Answer: We are looking to improve this. Currently the workflow is inside the CLI, so it’s a bit janky. https://www.unisonweb.org/docs/codebase-organization/#prs
But ultimately we hope to have something like the code review workflow on e.g. Gitlab
The potential here is enormous, and Unison makes it possible to make something insanely great for code reviews
Question: I was told that "names don't matter". Or maybe they do? I don't remember…
Answer: Since in Unison every expression has a canonical, automatically assigned “name” (the hash), other names are just window dressing, a UI for the programmer.
YOU MAY ALSO LIKE: