Sometimes you'll need to make a change in the codebase that can't automatically be propagated to dependent functions, for example: if you alter a data constructor for a type or change the arguments to a function. Unison can programmatically guide you through the edits that you need to make in these cases.
Note, your code which calls the old versions of a function will not bebroken(it'll still run as originally implemented) but it might refer to the old version by hash reference, which is how you end up with cryptic terms that look like this:
exclaim : Text
exclaim =
use Text ++
#7i0ceb20mm 4 ++ "!!"
This document walks through a workflow for making changes to your codebase and resolving the resulting conflicts in a way that helps to preserve the human readable names for your functions. 🤖
Walk through an example
Let's say we have a simple type and a function which makes use of that type:
unique type Box = Box Nat
Box.toText : Box -> Text
Box.toText box = match box with
Box.Box nat -> Nat.toText nat
Weadd
it to the codebase, and then later, we may realize its data constructor should be changed. The first thing we should do isfork
the namespace to create a new namespace where we'll be making our changes.
.> cd myWork
.> add
myWork.> fork .myWork .newFeature
In our new namespace, let'seditthe type:
myWork.> cd .newFeature
.newFeature> edit Box
We've changed the data constructor from taking a value of typeNat
toInt
.
unique type Box = Box Int
After making the change to the type we'llupdate
the codebase, and see if we have any functions or types to adjust given our change with thetodo
command. Remember, we're making these updates in our forked copy of the original namespace.
.newFeature> update
.newFeature> todo
🚧
The namespace has 1 transitive dependent(s) left to upgrade.
Your edit frontier is the dependents of these definitions:
unique type .myWork.Box
I recommend working on them in the following order:
1. toText : myWork.Box -> Text
We only have one todo item here, but in a more complicated codebase the suggested edit order from the UCM can be extremely helpful in prompting you to work from the "edges" of your codebase, working up the function call chain.
In this case, it looks like thetoText
function will need to be changed to point to theupdatedtype in this namespace and a few names and functions should be changed to handle theInt
.Because we've kept around a copy of the old data type the old namespace, the UCM renders it with its name instead of a cryptic hash.
-- old code
Box.toText : myWork.Box -> Text
Box.toText = cases myWork.Box.Box nat -> Nat.toText nat
-- new version ✨
Box.toText : newFeature.Box -> Text
Box.toText = cases newFeature.Box.Box int -> Int.toText int
When you're satisfied with the changes in your forked namespace and there are no moretodoitems, you canmergethe new namespace into the old namespace to fully replace the old implementation
.> merge newFeature myWork
There you have it! You've updated your codebase with the help of the UCM! 🌻