Defining terms

In Unison, we can give a value a name, for example:

favoritePie : Text
favoritePie = "Apple pie"

We call these definitions "term declarations", and they typically have two parts. The first, favoritePie : Text is the type signature, and it tells Unison and other programmers what type your term is. You might read this in human language as favoritePie has the type Text. Unison is able to infer the type of a given term so you might see this first part omitted for simple definitions.

The second line favoritePie = "Apple pie" supplies the implementation for your term.

🎨
By convention, types are capitalized in Unison, whereas term names are "camelCase."

The value assigned to a Unison term doesn't vary while a program is running, so if you try to reassign it like this:

favoritePie = "Apple pie"
favoritePie = "Peach pie"

The UCM will fail to typecheck:

I found 1 name with multiple definitions:

favoritePie

Tuples

Tuples are a way to join together values of different types into one value.

dessertOrder : (Text, Text, Nat)
dessertOrder = ("Alice", "Blueberry pie", 5)

A tuple is specific to the length of values joined together and the types of each of those values, so they're useful for structured data. There is no upper limit to the number of things you can put in a tuple in Unison.

If you try to add values to your tuple without changing the corresponding type, or supply a value of the wrong type, the UCM will fail to typecheck.

dessertOrder : (Text, Text, Nat)
dessertOrder = ("Alice", "Blueberry pie", "Chocolate cake", 2 )
I found a value  of type:  Text where I expected to find:  Nat

  38 | dessertOrder : (Text, Text, Nat)
  39 | dessertOrder = ("Alice", "Blueberry pie", "Chocolate cake", 2 )

  from right here:

  39 | dessertOrder = ("Alice", "Blueberry pie", "Chocolate cake", 2 )

When we want to un-tuple one of these values, we can use extraction functions which start with at1.

dessertOrder = ("Alice", "Blueberry pie", 5) at2 dessertOrder
"Blueberry pie"

Tuple pattern decomposition

Let's say you're working with data that's modeled by a tuple composed of a Text, a Bytes, and a Text. Later when writing a function which uses this tuple you might need to access the values at each position in the tuple and bind them to a variable name. You could do this with the at1, at2, and at3 functions defined on Tuple

getByteSize : (Text, Bytes, Text) -> Nat getByteSize tuple3 = use Bytes ++ use Text toUtf8 first = at1 tuple3 bytes = at2 tuple3 last = at3 tuple3 Bytes.size (toUtf8 first ++ bytes ++ toUtf8 last) getByteSize ("Shepherds", 0xsdeadbeef, "Pie")
16

But you can also rewrite the function to decompose the tuple into the desired variable names in one line. Just make sure the number of variables you're defining matches the tuple structure.

getByteSize : (Text, Bytes, Text) -> Nat
getByteSize tuple3 =
  _ = "tuple decomposition 👇"
  let
    (first, bytes, last) = tuple3
    size (toUtf8 first ++ bytes ++ toUtf8 last)
You can't decompose a tuple into terms at the top level of a Unison program. So (first, bytes, last) = ("Shepherds", 0xsdeadbeef, "Pie") outside of the body of another Unison function would fail to typecheck.

A few more types

We've seen a couple of basic types already, but here's a rudimentary vocabulary of Unison types to get you started writing Unison programs.

NamePurposeExample
Texttextual data"textBlob" or """multi-line text"""
Charsingle character?a
Bytesbyte literal0xsdeadbeef0d0a
Nat64 bit positive whole numbers. 0 to 2^64 - 15 Nat.+ 5
Int64 bit signed positive or negative whole numbers. -2^64/2 to 2^64/2 - 1+4 Int.- +9
Float64 bit floating point numbers3.14159
Booleantrue or false values for logictrue || false