# Functions¶

The type of functions with input X and output Y is written X -> Y. Some basic examples of function definitions are shown below.

example/function.disco
f : N -> N
f(x) = x + 7

g : Z -> Bool
g(n) = (n - 3) > 7

factorial : N -> N
factorial(0) = 1
factorial(n) = n * factorial(n .- 1)

• The function f takes a natural number as input, and returns the natural number which is 7 greater. Notice that f is defined using the syntax f(x) = .... In fact, the basic syntax for function arguments is juxtaposition, just as in Haskell; the syntax f x = ... would work as well. Stylistically, however, f(x) = ... is to be preferred, since it matches standard mathematical notation.
• The function g takes an integer n as input, and returns a boolean indicating whether n - 3 is greater than 7. Note that this function cannot be given the type N -> Bool, since it uses subtraction.
• The recursive function factorial computes the factorial of its input. Top-level functions such as factorial are allowed to be recursive. Notice also that factorial is defined by two cases, which are matched in order from top to bottom, just as in Haskell.

Functions can be given inputs using the same syntax:

Disco> f(2^5)
39
Disco> g(-5)
false
Disco> factorial(5 + 6)
39916800


“Multi-argument functions” can be written as functions which take a product type as input. (This is again a stylistic choice: disco certainly supports curried functions as well. But in either case, disco fundamentally supports only one-argument functions.) For example:

example/multi-arg-functions.disco
gcd : N * N -> N
gcd(a,0) = a
gcd(a,b) = gcd(b, a mod b)

discrim : Q * Q * Q -> Q
discrim(a,b,c) = b^2 - 4*a*c

manhattan : (Q*Q) * (Q*Q) -> Q
manhattan ((x1,y1), (x2,y2)) = abs (x1-x2) + abs (y1-y2)


All of these examples are in fact pattern-matching on their arguments, although this is most noticeable with the last example, which decomposes its input into a pair of pairs and gives a name to each component.

Functions in disco are first-class, and can be provided as input to another function or output from a function, stored in data structures, etc. For example, here is how one could write a higher-order function to take a function on natural numbers and produce a new function which iterates the original function three times:

example/higher-order.disco
thrice : (N -> N) -> (N -> N)
thrice(f)(n) = f(f(f(n)))


## Anonymous functions¶

The syntax for an anonymous function in disco consists of a lambda (either a backslash or an actual λ) followed by a pattern, a period, and an arbitrary disco expression (the body).

The pattern can be a single variable name or a more complex pattern. Note that patterns can also contain type annotations. Unlike in, say, Haskell, there is no special syntactic sugar for curried multi-argument functions; one can just write nested lambdas.

Here are a few examples to illustrate the possibilities:

Disco> thrice(\x. x*2)(1)
8
Disco> thrice(\z:Nat. z^2 + 2z + 1)(7)
17859076

## Operator functions¶

Operators can be manipulated as functions using the ~ notation. The tilde goes wherever the argument to the operator would go. This can be used, for example, to pass an operator to a higher-order function.

Disco> :type ~+~
~+~ : ℕ × ℕ → ℕ

Disco> import list