Complex Types

As well as the basic types, fi also allows the following complex types which usually work in conjunction with other types. Complex types can't be used in a literal way and have specific constructors for creating new variables.

Maps

Maps require a key and an element, and can form a large list of mapped elements. Keys must be unique for each entry, and can be used to retrieve a specific entry for a map.

A map key must be one of the following types:

  • string

  • bool

  • int

  • nat

  • bytes

  • mutez

  • timestamp

  • address

  • key_hash/pkh

We define the map type in the following way:

storage map[address => nat] balances;

This creates a map type variable, with a map key of type address, and a map item of type nat, stored as storage.balances.

Empty Map

An empty map can be defined using the following:

let map[int=>string] passages = new map(int, string);

Operations

The following operations can be used with maps

  • in(map, map_key) - returns bool if key exists as a map key in the map

  • length(map) - returns cardinal size of the map as a nat

  • get(map, map_key) - returns item with index key. Fails if key doesn't exist (it is advised to use in first)

  • push(map, map_key, map_item) - no return. Pushes item into map at index key. Will add the element if key doesn't exist, and update if it does (acts as an upsert)

  • drop(map, map_key) - no return. Removes the key/element pair from the map

These functions can be used as standalone functions, or as a variable modifier.

let map[int => string] textMap = new map(int, string);
push(textMap, int 1, "One");
textMap.push(int 2, "One"); // Same as above

Big Map

Big maps work the same as normal maps, but have a few restrictions:

  1. Big maps can only be declared as a storage variable

  2. Only one big_map can exist for any given contract

  3. The length() function doesn't work with big_maps

  4. Big maps can't be constructed

We define the map type in the following way:

storage bmap[address => nat] balances;

All functions, other then length, are applicable for big maps.

Lists

Lists are non-indexed arrays of a specified type, and are defined as follows:

let string[] names;

This creates a list of the specified type - in this instance a list of strings, which can be accessed via storage.names.

Empty list

An empty map can be defined using the following:

let string[] names = new list(string);

Operations

The following operations are available for lists:

  • length(list) - returns cardinal size of a list as a nat

  • push(list, item) - pushes an item to a list

  • pop(list) - removes the last item from a list and returns it

These functions can be used as standalone functions, or as a variable modifier.

let string[] names = new list(string);
push(names, "John");
names.push("Bill"); // Same as above

Set

Sets are similar to lists as we store a single type of data per entry, and can be declared as follows:

storage set[nat] numbers;

The set item type must be one of the following types (same as the map key):

  • string

  • bool

  • int

  • nat

  • bytes

  • mutez

  • timestamp

  • address

  • key_hash/pkh

Operations

The following operations are available for lists:

  • length(set) - returns cardinal size of a set as a nat

  • push(set, item) - pushes an item to a set

  • in(set, item) - returns bool if item exists in the set

  • drop(set, item) - no return. Removes the item from a set

These functions can be used as standalone functions, or as a variable modifier.

let set[string] names = new set(string);
push(names, "John");
names.push("Bill");

Contract

The contract type is the typed version of an address. Michelson contract types must also specify the type of the input parameter.

let contract[unit] implicit = to_contract(address "tz1...");

Option

Optional values can be set and then used within expressions. These values either hold "some" value, or "none". Optional values are defined by adding a question mark before another type:

let ?nat optional = to_optional(nat 100);

We can convert any existing value to an optional value using the to_optional cast, or we can use the none function to create an optional variable with no value.

let ?bool test = none(bool);
if (isset(test) == false) {
#This will execute
}