By and large, our CEO did, but the website content is open source and has been iterated on by many hands over the years. If you have suggestions, feel free to drop a note in a ticket: https://share.unison-lang.org/@unison/website
HN user
rlmark
That information is a bit out of date, though correct at the time. We've put the Chez Scheme interpreter on ice, and we focused on runtime improvements to the Haskell interpreter. So, currently, Unison compiles to Haskell.
If it helps, here's a side-by-side comparison guide between Java and Unison. It covers the syntax primarily: https://www.unison-lang.org/compare-lang/unison-for-java-dev...
Hey there! Apologies for not getting to you sooner. The `Table` is a storage primitive implemented on top of DynamoDB (it's a lower-level storage building block - as you've rightfully identified; these entities were made to be composable, so other storage types can be made with them). Our `OrderedTable` docs might be of interest to you: they talk about their own implementation a bit more (BTrees); and `OrderedTable` is one of our most ergonomic storage types: https://share.unison-lang.org/@unison/cloud/code/releases/23...
The Database abstraction helps scope and namespace (potentially many) tables. It is especially important in scoping transactions, since one of the things we wanted to support with our storage primitives is transactionality across multiple storage types.
Not a dumb question at all! Unison's type system uses Abilities (algebraic effects) for functional effect management. On a type level, that means we can prevent effects like "run arbitrary IO" on a distributed runtime. Things that run on shared infrastructure can be "sandboxed" and prevented with type safety.
The browser or mobile apps cannot execute arbitrary code on the server. Those would typically call regular Unison services in a standard API.
Great question.
There are indeed tradeoffs; as an example, one thing that trips folks up in the "save typed values without encoders" world is that a stored value of a type won't update when your codebase's version of the type updates. On its face, that should be a self-evident concern (solvable with versioning your records); but you'd be surprised how easy it is to `Table.write personV1` and later update the type in place without thinking about your already written records. I mention this because sometimes the lack of friction around working with one part of Unison introduces confusion where it juts against different mental models.
Other general tradeoffs, of course, include a team's tolerance for newness and experimentation. Our workflow has stabilized over the years, but it is still off the beaten path, and I know that can take time to adjust to.
I hope others who've used Unison will chime in with their tradeoffs.
Thank you! (And thanks for following along for all the years!)
I'll speak a bit to the language audience, and others might weigh in as they see fit. The target is pretty broad: Unison is a general-purpose functional language for devs or teams who want to build applications with a minimal amount of ceremony around writing and shipping applications.
Part of the challenge of talking about that (the above might sound specious and bland) is that the difference isn't necessarily a one-shot answer: everything from diffing branches to deploying code is built atop a different foundation. For example, in the small: I upgraded our standard lib in some of my projects and because it is a relatively stable library; it was a single command. In the large: right now we're working on a workflow orchestration engine; it uses our own Cloud (typed, provisioned in Unison code, tested locally, etc) and works by serializing, storing, and later resuming the continuation of a program. That kind of framework would be more onerous to build, deploy, and maintain in many other languages.
Thank you!
Unison does diverge a bit from the mainstream in terms of its design. There's a class of problems around deploying and serializing code that involve incidental complexity and repetitive work for many dev teams (IDLs at service boundaries and at storage boundaries, provisioning resources for cloud infrastructure) and a few "everyday programming" pain points that Unison does away with completely (non-semantic merge conflicts, dependency management resolution).
We wrote up some of that here at a high level: https://www.unison-lang.org/docs/what-problems-does-unison-s...
But also, feel free to ask more about the technical specifics if you'd like.
The tool you use to interact with the code database keeps track of the changes in an append-only log - if you're familiar with git, the commands for tracking changes echo those of git (push, pull, merge, etc) and many of them integrate with git tooling.
The projects in a codebase can absolutely be shared and versioned as well. Here's a log of release artifacts from a library as an example: https://share.unison-lang.org/@unison/base/releases.
That's still the case in Unison! This particular post doesn't dive into the codebase format, but the core idea is the same: Unison hashes your code by its AST and stores it in a database.
Totally fair, there are definitely tradeoffs.
The developer experience would be one of the main advantages. Unison cloud was custom built to run Unison's language without extra steps like building packages, syncing dependencies across nodes, etc. Also, interactions with other cloud platforms typically aren't described in a programming language which is shared between the infrastructure management layer and the application layer. The draw-back is that the Cloud runs the Unison programming language specifically.
Nice, a structural editor throwback reference! :-) I'll speak to point 1! We aim to add FFI as a fast follow on to the native compilation work that is underway. The work on the JIT compiler opens the door to FFI so that's on the roadmap soon.
Hi there! There's definitely an overhead to learning a new language but by describing your cloud infrastructure with an actual programming languages you reap the benefits of type-safety, testability, and code reuse, etc.
You're spot on with shifting the complexity to the cloud layer; our thought was that it would free up time for dev teams to focus on other layers of their application.
Maybe I'm misinterpreting your question though, I'm happy to annotate that code snippet with a walk-through.
We used to support git backed codebase hosting a while ago, before we launched our own remote hosting platform https://share.unison-lang.org/ and it had several downsides.
1. Unison terms are stored as hashes so checking in a binary file wasn't very ergonomic and didn't really enable much in terms of collaboration. If we store our code as text on the file system, we have less information than what's tracked in the Unison tooling, since the plain text version isn't aware of its dependencies. 2. Unison's versioning system is more syntactically aware than Git's since its granularity is based on the definition of your functions and types, not incidental changes like whitespace or newlines.
You can of course, bring all the Unison code for a program into a text file (you write Unison code in your regular editor) and then check it in, but that's not as nice of a workflow than the one that's supported directly.
We wrote an article speaking to this use case here: https://www.unison-lang.org/articles/distributed-datasets/ It's a bit of a deep dive into some of the building blocks of the Remote ecosystem - so it talks quite a bit about how you'd implement something like Spark itself in Unison, but you can see how running data aggregations would work on the Cloud.
At the point when you've written a term which is incidentally equivalent to another, the Unison codebase manager tool tells you that you're adding a term that is identical and lists its name. You can still technically perform the addition if you really want at that point, but most folks don't want two aliases for the same function floating around. If you do end up adding it, updating A would also update B. Think of the function name as metadata and the actual implementation as the identity of the function.
There is not, at present, an rclone library, but this would be a welcome addition to our open source cloud libraries. Perhaps your friend would like to write such a utility! :-)
I'll give it a shot; I think it's helpful to separate the Unison programming language from the Unison Cloud platform, as they're distinct things even though the features of one (the language) enable and are integrated with the other (the Cloud, which operationalizes the language for web apps and other cloud compute jobs).
Unison's core difference is that your code is not stored as regular text files; instead your functions and types are stored as a hash of their AST. This enables nice dependency management workflow and makes things like renaming functions trivial. The thing to remember is that your functions are programmatically tracked. Based on that core difference we built a platform that can deploy those arbitrary hashes (and all their dependencies) to different locations in a cluster, and we created a Unison library so that folks can describe how their code should be shipped across cloud computing resources. So you have Unison code describing and orchestrating Unison services.
That's a great question! (I work for Unison, full disclosure.)
The process for upgrading Unison code is that if you have a function A that calls B, and you update B in some way, as long as the change is type-preserving it will automatically be propagated to all the sites in your project where B is called. If the change is not type-preserving (for example, if you added a parameter) the tooling itself will direct you to resolve all the places where B is applied. So as you change code locally, you're continually keeping your codebase in sync; A will always be calling the updated function.
Here's an example from our docs: https://www.unison-lang.org/docs/usage-topics/workflow-how-t...
(Unison dev here) I hear you! :) `'` is easy to miss so we added the `do` keyword, and at least a few of us want to substitute `delay` as the keyword. Fortunately, we should be able to do that programmatically at the codebase level if the time comes for that, so folks won't have to hunt for their single quotes to change it everywhere.
Hi there! I can't speak to questions 1-3, but with regards to question 4, some of the examples we generated were born from early mistakes I had stumbled into when writing the `Tree` functions, so I have some thoughts. It would be interesting to codify the behavior of evaluating the `Tree` in more types, but looking back, the thing that would have helped me most in avoiding some of the missteps might have been a richer test interpreter, where I could have "mocked" a network of, say, 3 nodes and distributed the `Tree` across them, emitting information about where the data was being moved, and where the various functions were being applied. We had actually briefly thought about writing such an interpreter for the purpose of this article and it's still something I'd like to do at some point.
Hi there, the other article author chiming in here! You can perform side effects in Unison via abilities (our name for algebraic effects) - they're described here: https://www.unisonweb.org/docs/abilities/
Some basic IO functionality is supported by the `base` library (the standard lib) which contains functions like `openFile` which are effectful functions expressed in terms of the `IO` ability.