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
-
Expressions — The expression language used in function bodies
-
Pattern Matching — Destructuring arguments
-
Interfaces — Polymorphic dispatch