### Текстовое представление типов

Каждый тип (но не обязательно значения этого типа) имеет строковое представление, которое является валидной UTF-8 последовательностью.

## Общие правила

Все названия типов в текстовом представлении пишутся в `PascalCase`.

* За исключением примитивных типов данных (числа, строки и т.п.), которые представляются в текстовом виде просто своим именем, конкретный тип данных представляет собой композицию из других типов данных. Если представить эту композицию в виде дерева, то на листьях окажутся примитивные типы данных, а в остальных узлах — контейнеры. Специальные типы данных можно рассматривать как исключение, они могут находиться и там и там.
* Текстовое представление повторяет структуру этого дерева в порядке от корня к листьям: в каждом узле дерева указывается имя текущего типа данных, а переход на уровень глубже обозначается тем или иным видом скобок.
* Допустимо использование пробелов и переносов строк, если это улучшает читабельность.
* Строки в аргументах типов (названия полей в структурах/вариантах, тэг в Tagged) могут заключаться в одинарные кавычки.  Если строки состоят не только из латинских букв и цифр, то заключение в одинарные кавычки обязательно, при этом используется C-escaping.

В дальнейшем описании в фигурных скобках будем писать не-буквальные значения, например, в записи `List< {type} >` `{type}` будет означает
произвольный тип.

#### Типы без дополнительных аргументов

Представление совпадает с названием типа.
Список типов:

- `Int8`
- `Int16`
- `Int32`
- `Int64`
- `Uint8`
- `Uint16`
- `Uint32`
- `Uint64`
- `Null`
- `Void`
- `Float`
- `Double`
- `Bool`
- `String`
- `Utf8`
- `Date`
- `Datetime`
- `Timestamp`
- `TzDate`
- `TzDatetime`
- `TzTimestamp`
- `Interval`
- `Json`
- `Yson`
- `Uuid`
- `EmptyDict`
- `EmptyList`

#### Специальные типы
Чаще всего в специальных типах для задания параметров типа также используются угловые скобки.
Исключением является `Decimal`, в котором по историческим причинам используются круглые скобки.

##### Decimal
Имеет представление `Decimal({precision}, {scale})`, где `{precision}` и `{scale}` &mdash; целые числа.
Обратите внимание, что, в отличии от остальных типов, по историческим причинам используются круглые скобки.

Пример:
```
Decimal(10, 5)
```

##### Tagged
Имеет представление `Tagged<{item}, {tag}>`, где `{tag}` &mdash; строка с тэгом, `{item}` &mdash; представление underlying типа.

Пример:
```
Tagged<String, 'image/svg'>
```

#### Контейнеры

* Для указания типов элементов контейнера используются угловые скобки. Пример: `List<Int32>`.
* Если контейнер предполагает несколько разнородных элементов, то они перечисляются внутри угловых скобок через запятую. Пример: `Tuple<Int32,String>`.
* Если контейнер предполагает именованные элементы, то вместо просто типов данных через запятую используются пары из имени и типа через двоеточие. Пример: `Struct<a:Int32,b:String>`.
* Низлежащий тип для контейнера вариант выбирается в зависимости от наличия имён в аргументах. Пример: `Variant<Int32,String>` — вариант над кортежем, `Variant<a:Int32,b:String>` — вариант над структурой.

Ниже будут рассмотрены примеры.

##### Optional
Помимо записи `Optional<{type}>` допустима также запись с суффиксом `?`: `{type}?`.

Примеры:
```
Optional<Optional<Int64>>
Int64??
Optional<Yson>
Yson?
Optional<Decimal(10, 5)>
Decimal(10, 5)?
```

##### List
```
List<String>
List<List<Bool>>
```

##### Struct
```
Struct<foo: Int32, bar: Optional<String>>
Struct<'foo': Int32, 'bar': Optional<String>>
Struct<'I\'m fine': Int32, 'one slash \\': Optional<String>>
```

##### Tuple
```
Tuple<Double, Double, Int8>
```

##### Variant
```
Variant<'int_field': Int64, 'string_field': String>
Variant<Void, String>
```

##### Dict
Имеет представление `Dict<{key}, {value}>`, где `{key}` и `{value}` &mdash; представления типов ключа и значения соответственно.

Пример:
```
Dict<String, Optional<Int32>>
```

