Functions

Constants

A constant is a named value with a type annotation and a body expression:

greeting: Text
  "Hello, world!"

pi: Double
  3.14159

The type annotation appears on the first line after the colon. The body expression is indented on the next line.

Named Parameters

Functions declare named parameters in their type signature:

add: x:Integer. y:Integer. Integer
  x + y

greet: name:Text. Text
  "Hello, " ++ name

Each parameter has the form name:Type separated by dots. The final type after the last dot is the return type.

Multi-Argument Functions

Paradox is not a curried language. Multi-argument functions take all their arguments positionally at the call site:

add: x:Integer. y:Integer. Integer
  x + y

// Called with both arguments:
add 3 5

Higher-Order Functions

Functions can accept and return other functions:

apply: f:(a. b). x:a. b
  f x

compose: f:(a. b). g:(b. c). a:a. c
  g (f a)

flip: f:(a. b. c). b:b. a:a. c
  f a b

Function types are written with parentheses: (a. b) is a function from a to b.

Recursion

Functions can call themselves recursively:

fib: n:Integer. Integer
  match n:
    0: 0
    1: 1
    _: fib (n - 1) + fib (n - 2)
reduce: xs:[a]. f:(a. b. b). b:b. b
  match xs:
    []: b
    _: head. tail. f head (reduce tail f b)

Type Parameters

Functions can be polymorphic over type parameters. Type variables are lowercase identifiers that are universally quantified at the top level:

identity: x:a. a
  x

const: x:a. y:b. a
  x

flip: f:(a. b. c). b:b. a:a. c
  f a b

Paradox infers the type parameters from the signature — you don’t need to declare them separately.

Paradox does not support ranked types. All type variables are quantified at the outermost level of the function signature — you cannot require a polymorphic function as an argument (i.e., no forall inside argument positions).

See Also