Chapter 19 : Option

The option type is a predefined variant type that is used to express whether there is a value of some type or none. This is especially useful when calling a partial function, that is, a function that is not defined for some inputs. In that case, the value of the option type would be None, otherwise Some (v), where v is some meaningful value of any type.

An example in arithmetic is the division operation:

let div (a, b : nat * nat) : nat option =  if b = 0n then (None: nat option) else Some (a/b)

Initialization

The keyword Some can be used to create an option variable for a given value. The keyword None can be used to create an option variable with no given value.

let middleName : string option = Some "Foo";let noMiddleName : string option = None;

Option in Pattern matching

In the previous chapters, you’ve seen how to do pattern matching using the match with operator. The keyword Some can be used in a pattern matching to retrieve the value behind the option variable. The keyword None can be used in a pattern matching to verify the option variable has no value.

match <variable> with
  Some <value_name> -> <block_code>
| None -> <block_code>

<block_code> can be a single instruction or a function call <value_name> is a local variable name. <value_name> which holds the option value and can be used inside the <block_code>

Here is an example of accessing maps returning an option type and retrieving the value behind the optional :

type expected_type = int
type balance_type = (nat, expected_type) map
let user_balances: balance_type = Map.literal[ (1n, 10) ]

let one_balance_opt : expected_type option = Map.find_opt 1n user_balances 
let user_balance : expected_type = match one_balance_opt with
  Some v -> v
| None -> (failwith ("Unknown user"): expected_type)

It can be written in a single constant instruction :

let my_balance : expected_type = match Map.find_opt 1n user_balances with
  Some v -> v
| None -> (failwith ("Unknown user") : expected_type)

Notice the cast of failwith instruction into an expected\type_

Your mission

1- Notice the weapons mapping which maps the name of each weapon to its corresponding input of power. We want to increase the power of the Main Laser but mapping returns optional results as they might not be found in the mapping. Define the constant main_laser_power_opt as an optional int from selecting “Main Laser” from the weapons mapping.

2- Create a constant increased_weapons representing the new weapon mapping and initialize it with a pattern matching on main_laser_power_opt. If it exists, update weapons mapping by increasing the power of the “Main Laser” by 1 (use i as temporary matching variable). If it does not exist in the mapping, fail with “Weapon not found”