# Algebraic data types

In functional programming and type theory, an algebraic data type (ADT) is a kind of composite type, formed of two or more other primitive types.

``type MyAdt =  | MyConstructor1 of Int32 String  | MyConstructor2 of ByStr20  | MyConstructor3``

An ADT is defined using one or more constructors (not to be confused with constructors from object-oriented languages). A value of type MyAdt is constructed using exactly one of these constructors. In this example, a `MyAdt` value constructed using `MyConstructor1` will contain a tuple comprised of an Int32 value and a String value. A MyAdt value constructed using MyConstructor3 on the other hand will not contain any further values inside it.

The example we saw previously defines an ADT whose composite types are fixed. A polymorphic ADT allows using type variables in place of concrete constituent types, for substitution later. Let's see an example.

``type 'A MyPAdt =  | MyPConstructor1 of 'A String  | MyPConstructor2 of ByStr20  | MyPConstructor3``

`MyPAdt` is a polymorphic ADT with a type parameter (variable) `'A`. When `MyPAdt` is, for example, instantiated with the type parameter `'A` set to `Int32`, then MyPAdt will share the same structure as `MyAdt`. `List`, the Scilla built-in ADT is, for example, a polymorphic ADT. When we write `List Int32`, it means that we have instantiated `List` ADT with `Int32`. This built-in ADT, if it wasn't built-in, would look like:

``type 'A List =  | Cons of 'A ('A List)  | Nil``

At the moment, Scilla does not support user-defined polymorphic ADTs. Only the built-in ADTs `List`, `Pair` and `Option` are polymorphic. Users can only define concrete ADTs such as `MyAdt`.

:::warn You cannot remote state read a data structure which holds an ADT. :::

### Bool#

``my_bool = True``

### Option#

``````let none_value = None {ByStr20}
field staging_owner: Option ByStr20 = none_value
transition Test(optional_staging : Option ByStr20)  match new_staging with    | Some staging_value =>      staging_owner := staging_value    | None =>  endend``````

### List#

``field state_list_users : List ByStr20 = Nil {ByStr20}transition Test()  current_list <- state_list_users;  new_user = Cons {ByStr20} _sender current_list;  state_list_users := new_userend``

### Pair#

``````field state_user_pairs : Map ByStr20 (Pair ByStr20 Uint128)
transition Test(delegator: ByStr20, user: ByStr20, amount: Uint128)  pair_example = Pair {ByStr20 Uint128} _sender user;  state_user_pairs[delegator] : pair_exampleend
``````

### Nat#

``````field state_nat : Nat = Zero
current_nat <- state_nat;
let x =  let nat_plus_one  = Succ current_nat
``````

### User-defined#

``````type SwapDirection = | ZilToToken | TokenToZil
procedure Example(direction: SwapDirection)    match direction with      | ZilToToken =>       | TokenToZil =>     endend``````
``````type Pool = | Pool of Uint128 Uint128
procedure Example(pool: Pool)  match pool with    | Pool x y =>  endend``````
``````type Game = | Game of (Option ByStr20) Uint128
procedure Example(game: Game)  match game with    | Game maybe_bystr game_int =>      (* At this point you have the Optional and the int value*)      match maybe_bystr with        | Some some_bystr =>          (* At this point you have Some bystr20 value and the int value *)        | None =>          (* At this point you have only the int value*)      end  endend``````

### Store ADT as List (Pair Parcel Uint32)#

``````scilla_version 0(****************************************************************************)(*   user defined algebraic data type (ADT) examples:                       *)(*   a Parcel with a content consisting of one or two Item(s)               *)(*   A single Item can be a Shirt or a Barbell and has a weight             *)(*   A Parcel can have one Item or two Items in it and depending on the     *)(*   total weight has a cost to ship assigned to it                         *)(****************************************************************************)library Adt
type Item = (* constructor argument is the weight of the item *)  | Shirt of Uint32  | Barbell of Uint32
type Parcel =  | OneContent of Item (* a parcel with a single item as content *)  | TwoContents of Item Item (* a parcel can be filled with 2 items *)
let weight_of_item = fun(i: Item) => (* how much an item weighs *)  match i with  | Shirt w => w  | Barbell w => w  end
let cost_per_weight = Uint32 5
let cost_of_parcel = fun(p: Parcel) => (* cost to ship the parcel *)  let weight =    match p with    | OneContent c => (* parcel has only one item as content *)        weight_of_item c    | TwoContents c1 c2 => (* parcel has two items as content *)        let w1 = weight_of_item c1 in        let w2 = weight_of_item c2 in        builtin add w1 w2 (* total weight is sum of the two *)    end in  builtin mul weight cost_per_weight (* cost is total weight times cost_per_weight *)

(* mutable fields declarations *)field parcels : List (Pair Parcel Uint32) = Nil {(Pair Parcel Uint32)} (* a list of parcels and their cost to ship *)
procedure ComputeCostAndAdd(p: Parcel)  (* compute cost to ship the new parcel *)  cost = cost_of_parcel p;  (* add it to the list of parcels *)  l <- parcels;  pair = Pair {Parcel Uint32} p cost;  new_list = Cons {(Pair Parcel Uint32)} pair l; (* front insert *)  parcels := new_list;  ev = {_eventname : "AddToListOfParcelsSuccess"; cost_to_ship: cost; parcels: new_list};  event evend
(* add parcels with different items to the list of parcels *)transition AddParcelWithShirt(weight: Uint32)  c = Shirt weight;  p = OneContent c;  ComputeCostAndAdd pend
transition AddParcelWithBarbell(weight: Uint32)  c = Barbell weight;  p = OneContent c;  ComputeCostAndAdd pend
transition AddParcelWithTwoShirts(weight1: Uint32, weight2: Uint32)  c1 = Shirt weight1;  c2 = Shirt weight2;  p = TwoContents c1 c2;  ComputeCostAndAdd pend
transition AddParcelWithShirtAndBarbell(weightS: Uint32, weightB: Uint32)  c1 = Shirt weightS;  c2 = Barbell weightB;  p = TwoContents c1 c2;  ComputeCostAndAdd pend``````

### Store ADT as Map ByStr20 Player#

``````scilla_version 0(************************************************************************)(* a map of ByStr20 (address) to a user defined algebraic data type     *)(*   the ADT is a Player with an age that either plays tennis or runs   *)(************************************************************************)library ADTMap
type Sport =  | Tennis  | Run
type Player = | Player of Uint32 Sport (* Age and preferred Sport *)