# Composed Types

## Option

Options represents a value that could be defined *Some(value)* or not *None*.

```csharp
const a: nat option = None;
const b: nat option = Some(12n);
```

The option type offers some helpers:

```csharp
const c: bool = isNone(a); // returns true if a is None
const d: bool = isSome(a); // returns true if a is Some(_)
const e: nat = getSome(b): // extract the value (if any) or fail
```

## List

List type represents list of same-type elements; a list can be declared as follow:

```csharp
let l: nat list = (List.empty(): nat list); // empty list
let l1: nat list = [12n, 13n]; // literal list
```

```csharp
let ls: nat = l.size();
```

```csharp
let lh: nat = l.head();
```

```csharp
let lt: nat list = l.tail();
```

```csharp
let l2: nat list = l.prepend(14n);
```

```csharp
let l3: nat list = l.mapWith((a: nat) => (a * 2n));
```

```csharp
let l4: nat list = l.filter((a: nat) => (a <= 13n));
```

{% hint style="info" %}
*prepend*, *mapWith* and *filter* are applied in-place if used over storage fields. Their types are *unit* instead of *nat list.* To apply as expression, surround the storage field with *copy()*.
{% endhint %}

## Set

Sets are list of different elements of the same-type.

```csharp
let s: nat set = (Set.empty(): nat set); // empty set
let s1: nat set = ([12n, 13n]: nat set); // literal set
```

```csharp
let ss: nat = s.size();
```

```csharp
let b: bool = s.mem(13n);
```

```csharp
let s2: nat set = s1.update(18n, true); // add
let s2: nat set = s2.update(18n, false); // remove
```

```csharp
let ssum: nat = s2.fold((acc: nat, l: nat) => (acc + l), 0n);
```

{% hint style="info" %}
*update* are applied in-place if used over storage fields. Their types are *unit* instead of *nat set.* To apply as expression, surround the storage field with *copy()*.
{% endhint %}

## Tuple

A tuple is a pair, triple, etc of different types; you can define a tuple as follow:

```csharp
let atuple: (int, string) = (12, "hello");
```

## Record

## Map & Big\_map

('a, 'b) Map and ('a, 'b) Big\_map are collections of *'b* indexed by a key *'a*; *'a* should be a comparable.

{% hint style="info" %}
*update, remove, mapWith, fold, filter* are applied in-place if used over storage fields. Their types are *unit* instead of *nat set.* To apply as expression, surround the storage field with *copy()*.
{% endhint %}

### Map

```csharp
let m: (string, nat) map = (Map.empty(): (string, nat) map);
```

```csharp
let m: (string, nat) map = [ { "Hello": 12 } ];
```

```csharp
let a: nat = m.size();
```

```csharp
let b: nat = m.get("Ciao", 0); // failsafe get
let b1: nat = m.get("Ciao"); // failable get
let c: nat option = m.getOpt("Ciao");
```

```csharp
let b: bool = m.mem("Ciao");
```

```csharp
let c: nat = m.fold((acc: nat, k: string, v: nat) => (acc+v), 0n);
```

```csharp
let m2: (string, nat) map = m.mapWith((k: string, v: nat) => (v * 2n)); 
```

```csharp
let m2: (string, nat) map = m.filter((k: string, v: nat) => (v > 2n)); 
```

```csharp
let m2: (string, nat) map = m.remove("Hello"); 
```

```csharp
let m2: (string, nat) map = m.update("Hello", 42n); 
```

### Big\_map

```csharp
let bm: (string, nat) big_map = (BigMap.empty(): (string, nat) big_map);
```

```csharp
let b: nat = bm.get("Ciao", 0); // failsafe get
let b1: nat = bm.get("Ciao"); // failable get
let c: nat option = bm.getOpt("Ciao");
```

```csharp
let b: bool = bm.mem("Ciao");
```

```csharp
let bm2: (string, nat) big_map = m.remove("Hello"); 
```

```csharp
let bm2: (string, nat) big_map = bm.update("Hello", 42n); 
```

## Lambda

Lambda type represent anonymous functions.

```csharp
const e_sum: int -> int = (a: int) => (0 + 1);
const e_gt: int -> bool = (a: int) => (0 > 1);
const e_gt2: int -> bool = (a: int) => (a > 1);
const e_comp: (int, int) -> bool = (a: int, b: int) => ((a * 8) > (b - 12));
const e_comp2: (int, int) -> bool = (a: int, b: int) => ((a * (b - 8)) > (b - 12));
const e_apply: int -> bool = (a: int) => (e_comp (12, 13));

const e_apply2: int -> int = (a: int) => (((b: int) => (b))(12));
const e_apply3: int -> int = (a: int) => (e_apply2 (12));
```

## In-place modification

While calling some of the composed type specific functions, if the left-hand is storage field, the modification will be automatically assigned to the field storage.

```csharp
this.flist.prepend (12n); // this has type unit, an modify flist prepending 12n
```

To avoid this behaviour, you can use the *copy* helper function.

```csharp
let a: nat list = copy(this.flist).prepend(12n);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gessadavide.gitbook.io/yallo-lang/docs/types/composed-types.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
