--- navhome: /docs/ sort: 15 next: true title: Basic types --- # Basic types A Hoon `type` is a set of nouns. There is no syntax for directly defining the data type of a Hoon expression. Instead, the compiler infers the type of a Hoon expression by calculating the range of possible values of that expression. Working with a type in Hoon requires the use of a `mold`. Each type is defined by a mold. To define a custom type, you must create a custom mold. ## Molds A mathematical function is a mapping from one set (the domain) to another (the range). Pass an object from the domain to some function *f*, and *f* returns an object from the range. In Hoon we can think of a `gate` as a function, where the gate's `sample` is its argument. A `mold` is an idempotent function (i.e., gate) that takes any noun as its input (i.e., its domain is the set of all nouns). An idempotent function *f* is one such that, if *f(x)* terminates, *f(x) = f(f(x))*. The product range of a mold is the type defined by that mold. That is, each mold's type is the set of possible outputs of that mold. Essentially, molds are constructor functions. You can pass a mold any data you like, and the product is guaranteed be of the type defined by that mold. Molds are the perfect tool for validating untrusted foreign data: just call the relevant mold with that data. But this use case is unusual for beginners; otherwise you shouldn't call molds directly. More frequently, molds are used when we want to `cast`. We use a cast when we want the Hoon compiler's type-checker to test whether a Hoon expression is guaranteed to evaluate to a product of the desired type. If it isn't, then the compiler will halt with a `nest-fail` crash. Proper Hoon code will include a cast for each gate. The `^` family of runes is for casting. In particular, `^-` allows us to cast with a mold. For example, we can cast for an `atom` using the `@` mold as follows: ``` ^-(@ 17) ``` Evaluating the above in `dojo` should return 17, because 17 is of the type `atom`. On the other hand, ``` ^-(@ [17 18]) ``` ...this should result in a `nest-fail`, because `[17 18]` is a cell, not an atom. See the documentation on the `^` family of runes for more information on casts. See the documentation on the `$` family of runes for building molds. (Also check out the irregular `,` operator.) ## `type`: a set of types Below is the mold for `type`, written in Hoon. This mold's range is the set of all types. (Don't let yourself get too dizzy thinking about it! Strictly speaking, the range is of trees of type-*labels* used by the compiler's type-checker. We don't mess around with set-theoretic paradoxes.) You haven't seen this syntax before, and we haven't explained it yet; just treat it as pseudocode. This is a slightly simplified version of `type`. We undo and explain the simplifications in the [advanced types](../advanced) section. ``` ++ term @tas ++ type $@ $? $noun $void == $% {$atom p/term q/(unit atom)} {$cell p/type q/type} {$core p/type q/(map term hoon)} {$face p/term q/type} {$fork p/(set type)} {$hold p/type q/hoon} == ``` If a type is an atom, it's labelled with either the atomic string `%noun` or `%void`; if a cell, it's labelled with a tuple with one of the heads `%atom`, `%cell`, `%core`, etc. We'll go through each of these cases below. ### `?($noun $void)` `%noun` is the label for the set of all nouns. `%void` is the label for the empty set. (For now, don't worry too much about the switch from `$` to `%`.) ### `{$cell p/type q/type}` `[%cell p/type q/type]` is for the set of all cells with head `p` and tail `q`. ### `{$fork p/(set type)}` `[%fork p/(set type)]` is for the union of all types in the set `p`. ### `{$hold p/type q/hoon}` A `%hold` type, with type `p` and hoon `q`, is a lazy reference to the type of `(mint p q)`. In English, it means: "the type of the product when we compile `q` against subject `p`." ### `{$face p/term q/type}` A `[%face p/term q/type]` wraps the label `p` around the type `q`. `p` is a `term` or `@tas`, an atomic ASCII string which obeys symbol rules: lowercase and digit only, infix hyphen, first character must be lowercase. See [`:limb`](../twig/limb/limb) for how labels are resolved. It's nontrivial. ### `{%atom p/term q/(unit atom))}` `%atom` is for an atom, with two twists. `q` is a `unit`, Hoon's equivalent of a nullable pointer or a Haskell `Maybe`. If `q` is `~`, null, the type is *warm*; any atom is in the type. If `q` is `[~ x]`, where `x` is any atom, the type is *cold*; its only legal value is the constant `x`. `p` in the atom is a terminal used as an *aura*, or soft atom type. Auras are a lightweight, advisory representation of the units, semantics, and/or syntax of an atom. An aura is an atomic string; two auras are compatible if one is a prefix of the other. For instance, `@t` means UTF-8 text (LSB low), `@ta` means ASCII text, and `@tas` means an ASCII symbol. `@u` means an unsigned integer, `@ud` an unsigned decimal, `@ux` an unsigned hexadecimal. You can use a `@ud` atom as a `@u` or vice versa, but not as a `@tas`. Auras can also end with an optional, capitalized suffix, which defines the atom's bitwidth as a log starting from `A`. For example, `@udD` is an unsigned decimal byte; `@uxG` is an unsigned 64-bit hexadecimal. You can make up your own auras and are encouraged to do so, but here are some conventions bound to constant syntax: ``` @c UTF-32 codepoint @d date @da absolute date @dr relative date (ie, timespan) @n nil @p phonemic base (plot) @r IEEE floating-point @rd double precision (64 bits) @rh half precision (16 bits) @rq quad precision (128 bits) @rs single precision (32 bits) @s signed integer, sign bit low @sb signed binary @sd signed decimal @sv signed base32 @sw signed base64 @sx signed hexadecimal @t UTF-8 text (cord) @ta ASCII text (span) @tas ASCII symbol (term) @u unsigned integer @ub unsigned binary @ud unsigned decimal @uv unsigned base32 @uw unsigned base64 @ux unsigned hexadecimal ``` Auras are truly soft; you can turn any aura into any other, statically, by casting through the empty aura `@`. Hoon is not dependently typed and can't statically enforce data constraints (for example, it can't enforce that a `@tas` is really a symbol). ### `{$core p/type q/(map term type)}` `%core` is for a code-data cell. The data (or *payload*) is the tail; the code (or *battery*) is the head. `p`, a type, is the type of the payload. `q`, a name-hoon table, is the source code for the battery. Each hoon in the battery source is compiled to a formula, with the core itself as the subject. The battery is a tree of these formulas, or *arms*. An arm is a computed attribute against its core. All code-data structures in normal languages (functions, objects, modules, etc) become cores in Hoon. A Hoon battery looks a bit like a method table, but not every arm is a "method" in the OO sense. An arm is a computed attribute. A method is an arm whose product is a Hoon function (or *gate*). A gate (function, lambda, etc) is a core with one arm, whose name is the empty symbol `$`, and a payload whose shape is `{sample context}`. The *context* is the subject in which the gate was defined; the *sample* is the argument. To call this function on an argument `x`, replace the sample (at tree address `6` in the core) with `x`, then compute the arm. (Of course, we don't mutate the noun, we make a mutant copy.)