Functions and Arguments
A type function takes a type as its argument, returns a type, or does both. Its defining feature is that the material it manipulates is a type.
Predicting When a Type Function Runs
Most of the functions you have written so far probably follow a familiar pattern: you pass in a value, the function does some work, and you get back another value. Before reading further, try to hold that picture in mind, because this article introduces a function that works differently. A type function is a building block that programmers and library implementers can use, and the key questions for understanding it are simple: what goes into a type function, what comes out, and when the work happens.
What do you think happens?
When does a type function do its work: while the program is running, or earlier?
Reveal answer
Before the program starts executing, during compilation
A type function is evaluated at compile-time, not while the program runs. The most important word in its definition is compile-time, because it marks the difference between a type function and the ordinary functions most learners are used to.
From Values to Types
An ordinary function works with values. You pass in a number, a string, or a list, and you receive another value back. A type function changes the kind of thing that flows through the function. Instead of working with values, it works with types. The idea is that the type itself becomes the material that a function manipulates.
Think of the difference as a change in what sits on the conveyor belt. In an ordinary function, the items entering are data, such as a particular number or string. In a type function, the items entering are descriptions of kinds of things. The function's machinery is the same general idea of taking an input and producing an output, but the input and output are about the structure or properties of types rather than about any particular piece of runtime data.
A type function takes a type as its argument, returns a type, or does both. Its defining feature is that the material it manipulates is a type.
Tracing Input, Function, and Output
A helpful way to understand a type function is to follow a type through it step by step. Imagine giving a type function a type as its argument. The function is evaluated at compile-time and produces a result. Because the input is a type, the work concerns the structure or properties of that type, not any particular runtime data. The diagram below traces this path from the type going in, through the function, to the result coming out.
The three questions from the opening, what goes in, what comes out, and when the work happens, are all answered by this path. The input is a type. The work is evaluated during compilation. The output is a result that is already settled by the time the program starts doing its ordinary work.
Two Shapes of a Type Function
The definition names two possibilities separated by the word or. A type function may accept a type and return something else, or it may accept something and return a type. The source describes both shapes as belonging to one concept, so treat them as two variations of the same idea rather than two unrelated tools. The comparison below places the two shapes side by side so you can see where the input and output sit in each.
| Shape | What goes in | What comes out |
|---|---|---|
| Takes a type | A type | Something else |
| Returns a type | Something else | A type |
The two shapes described by the definition, both variations of one concept
When the Work Happens
Timing is what separates a type function from the ordinary functions most learners know. A type function is evaluated while the program is being compiled, not while it is running. The work of deciding the type happens before the program executes, so the result is already settled by the time the program starts doing its ordinary work. The timeline below shows where the type function's evaluation sits relative to the start of program execution.
The result of a type function is already determined before the program begins its ordinary execution. That is why it is described as happening at compile-time rather than at runtime.
Worked Trace of a Type Through a Function
Tracing a type through a type function
A programmer has a type function that accepts a type as its argument and returns a result. The programmer wants to trace what happens to the type from the moment it is supplied until the result is available. This example is illustrative and uses generic names rather than any specific library function.
- 1Identify the input
The argument is a type, not a value. Nothing about any runtime data matters yet, because the function is working on the type itself.
- 2Locate the evaluation moment
The function is evaluated at compile-time, during compilation, before the program starts executing.
- 3Follow the work
The function examines the structure or properties of the type it received and computes its result from them.
- 4Identify the output
The output is the result the function produces. Because this type function accepts a type and returns something else, the result is not necessarily a type.
- 5Confirm settlement
When the program starts its ordinary work, the result has already been decided. The program uses it rather than computing it during execution.
The type entered as the argument, was processed during compilation, and the settled result was ready before the program began running.
Common Misconceptions About Type Functions
Because type functions look like the functions learners already know, several wrong assumptions are easy to make. The items below name the most common ones and correct them using the timing and shape ideas covered above.
Common mistake Believing a type function runs while the program is executing
Why it failsThe defining word in the definition is compile-time. A type function is evaluated while the program is being compiled, before the program starts doing its ordinary work.
Do this insteadTreat the type function's result as already settled when the program begins running.
Common mistake Assuming a type function always takes a type as input
Why it failsThe definition allows two shapes joined by or. A type function may accept a type and return something else, or accept something and return a type.
Do this insteadCheck which position the type occupies, input or output, before reasoning about the function.
Common mistake Treating the two shapes as unrelated tools
Why it failsThe source describes both shapes as belonging to one concept, so they are variations of the same idea.
Do this insteadApply the same questions to both: what goes in, what comes out, and when the work happens.
Common mistake Expecting a type function to behave like a function operating on runtime values
Why it failsBecause the input is a type, the work concerns the structure or properties of that type rather than any particular runtime data.
Do this insteadAsk what property of the type matters, not what value the program holds at a given moment.
Practice Tracing Type Functions
A type function is described as accepting a type and returning something else. Trace it in three parts: name the input, name the output, and state the moment the work happens. Then explain why the program can use the result as soon as ordinary execution begins.
Hints
- The input position is a type in this shape, so start there.
- Remember the word compile-time when you decide the timing.
- The result is settled before the program starts, so it is not recomputed during ordinary execution.
Carrying the Idea Forward
Type functions extend the familiar idea of a function from values to types. The standard library provides a variety of ready-made type functions, so you do not need to invent them yourself. Their purpose is to help programmers and library implementers write code that takes advantage of the language, the standard library, and code in general. A dependable type function gives you a reliable way to ask a question about types or to produce a type, and you can build on that answer in your own code.
Key Takeaways
- A type function is evaluated at compile-time, not while the program runs, so its result is settled before ordinary execution begins.
- A type function takes a type as its argument, returns a type, or does both, and the material it manipulates is a type rather than a value.
- The two shapes, accepting a type and returning something else or accepting something and returning a type, are variations of one concept.
- Tracing a type means identifying the input type, the compile-time evaluation, and the settled output that the program later uses.