Tokens

The following tokens do exist

TokenNamePurpose
{}Left / Right BracesSet Types; Interpolation together with the $-Token;
[]Left / Right BracketsList Types
()Left / Right ParensStructure Types,override precedence
@AtBinding Typed values to names
::Double ColonDeclares the type (RHS) of name (LHS)
.DotUsed to create explicit float values; Usage for accessing child properties in sets is not yet implemented. Some usage example: 0.1 .5e-9 5.e2 (This is just native nix)
?QuestionOptional properties of sets
;SemicolonTerminate set entries
->ImplicationDefine Lambdas e.g. Int -> String
//UpdateUpdate Attribute Set Types. Can be used to partially update and insert name-value-types
-SubUsed for explicit negative numbers (-2.0), subtraction is NOT supported (e.g 3 - 1)
<>PathDefine valid paths as explicit values
|PipeCreate Type-Unions e.g. Int | Float
${}InterpolationUsed for naming / referring to dynamic names
"String body (single-line)explicit string values
''String body (multi-line)explicit string values
[0-9]*Integerexplicit integer values

Tokens removed

In contrast to the default nix language, some tokens do not exist and may even result in an error.

TokenNamePurpose
,CommaOriginally used for separation in lambda-patterns, replaced by ; (Semicolon)
:ColonOriginally used for lambda, patterns; in Type context replaced by ->
=AssignDoes not exists, use :: (Double Colon) to declare
++ConcatDoes not exists, use | (Pipe) to create list unions
/DivNot used
/**/Multiline CommentNot used
+AddNot used
*MulNot used
&&Andnot used
||Ornot used, use single | (Pipe)
< <=, =>, >Less, Less or equal, More or equal, Morecomparison not used

The following keywords do exist

Only the let .. in keywords are supported.

KeywordPurpose
letdeclaration block
inwhat is yielded

Keywords removed

As complexity is already quite high. It is considered best to not support the following keywords in the type language.

Keyword
assert
if
else
then
inherit
or
rec
with

Reserved Types

All types are written in Uppercase by convention to visually distinguish them from variables and actual values.

Some composed types are handled as native types as well. They are well-defined internally but can be used natively in the type language.

Keyword
Bool
Int
Float
String
Path
Null
Number
Derivation

_Internal context

ContextPurpose
MultilineCommentBodyInitial Context, every character is just the content of the comment.
TypeBlockStarted by {whitespace}Type:; Every following character is tokenized with the type grammar.
ExampleBlockStarted by {whitespace}Example:; Everything followed is just a comment string content. Token may not be needed?
StringBody; StringEnd; Interpol; InterpolStart; PathRegular nix tokenization context

Syntax

-- under construction --

The syntax very closely follows the Nix syntax to make writing types intuitive for Nix users. Although the language is inspired by Haskell, not every Nix user may be familiar with Haskell.

Legacy let

Did you know the legacy let? Don't bother it is legacy ^^ ;-). Legacy let is not supported by the type language. In general, every type is defined in a type expression.

e.g.

Int | Bool

is a type expression; - but also

let
Foo :: Int;
in
Foo | Bool

Those two examples contain essentially almost every rule for writing type expressions.

As shown in general there are two levels of type expression.

  • Type-expression
  • Simple Type-expression

The everything is a Type Expression but in certain places you can only write simple type expression. This behavior is not invented with the type language; it is derived from nix. Where the same principles apply.

For example Simple type expressions do not ally writing let ... in.

[ let T :: Int in T ]

is just NOT allowed. There are certain places within the syntax where you can only write simple expressions such as:

[ {SIMPLE} ] -> [ Int | String ]

Root Ident

Currently, there are many so-called root ident nodes.

Example:

    mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet