The official documentation about the operators in nix can be found here

🚧🚧🚧 This site is WIP

Official List

Attribute selectionAttrSet . AttrPath [ or expr ]none1
Function applicationfunc exprleft2
Arithmetic negation- numbernone3
Has attributeAttrSet ? AttrPathnone4
ist concatenationlist ++ listright5
Multiplicationnumber * numberleft6
Divisionnumber / numberleft6
Subtractionnumber - numberleft7
Additionnumber + numberleft7
String concatenationstring + stringleft7
Path concatenationpath + pathleft7
Path and string concatenationpath + stringleft7
String and path concatenationstring + pathleft7
Logical negation (NOT)! boolnone8
UpdateAttrSet // AttrSetright9
Less thanexpr < exprnone10
Less than or equal toexpr <= exprnone10
Greater thanexpr > exprnone10
Greater than or equal toexpr >= exprnone10
Equalityexpr == exprnone11
Inequalityexpr != exprnone11
Logical conjunction (AND)bool && boolleft12
Logical disjunction (OR)bool \|\| boolleft13
Logical implicationbool -> boolnone14

Type signatures

From a type perspective those operators can be seen as lambda functions. Every operator takes arguments of one type and returns a type. The following list was created to clarify the type signatures.

Some operators take one or two arguments, they can either take them from left or right hand side.

Some formals

for simplicity

  • R is used as Right hand side type.
  • L is used as Left hand side type.
  • When using the proposed lambda notation, the first argument is always LHS and the second the RHS of the discussed operator.
  • T,U,W are used as generic Type variables mostly do denote the resulting type, or types of free variables.
  • a,b,... can be of any type. They are type variables.
  • x is a functions input value
  • y is a functions return value

'.' - Attribute selection

Usage of the (.) operator:

L must be an AttrSet, and R must evaluate to type String

If R itself contains an expression this is parenthesized with the ${ } operator. This operator tells the parser to evaluate the expression in R before passing it to the (.) function.

 L(.)R = L.R 
 L(.)R = L -> R -> T
 L(.)R :: { ${name} :: a } -> String -> a

Function application

Let f be a function; x its applied argument and y the applied function result.

 y = f x

For comprehensiveness let the type signature of the above function be L and the applied argument R.

blow the argument R is applied to a function of type L.

 L R = L -> R -> T
 L R :: (a -> b) -> a -> b 

'-' - minus operator

 y = x - 1

(-) is a special case where the RHS is applied first to the function. So if the LHS was omitted it gets the value 0 as type Int.

 L(-)R :: R -> L -> T
 (-) :: ( Int | Float ) -> ( Int | Float | 0 ) -> (Int | Float)

The minus operator is a dependent type It depends on the received argument value

  • If it receives two Int types it returns Int
  • but if one or both of its arguments is of type Float it returns type Float
  • The type signature is correct using the Number type, but it lacks the information about its value dependency.

'+' - plus operator

'?' - Has attribute

'++' - List concatenation

'<' '>' - comparison

'==' - Equality

'!=' - Inequality

'*' - Multiplication

'!' - Negation

'//' - Update

'&&' '||' '->' - Logical