Concepts / Functions and Arguments

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.

  • Programming

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?

  • While the program is running, one step at a time

  • Before the program starts executing, during compilation

Reveal answer
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.

Key point

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.

Type as inputthe argumentType functionevaluated at compile-timeResultproduced by the functionentersproduces
What happens to a type as it enters a type function, and what comes out the other end?

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.

Input: a typeOutput: somethingelseInput: somethingOutput: a typefunction maps tofunction maps to
How do the input and output positions differ between a type function that accepts a type and one that produces a type?
ShapeWhat goes inWhat comes out
Takes a typeA typeSomething else
Returns a typeSomething elseA 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.

Source code writtenCompilationtype function evaluatedProgram startsOrdinary workuses the settled typeresultthenthenthen
At which stage of the build-and-run process is the type function evaluated, and which steps happen before the program starts executing?
Key point

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

Worked example

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.

  1. 1
    Identify 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.

  2. 2
    Locate the evaluation moment

    The function is evaluated at compile-time, during compilation, before the program starts executing.

  3. 3
    Follow the work

    The function examines the structure or properties of the type it received and computes its result from them.

  4. 4
    Identify 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.

  5. 5
    Confirm settlement

    When the program starts its ordinary work, the result has already been decided. The program uses it rather than computing it during execution.

Result

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 fails

    The 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 instead

    Treat 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 fails

    The 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 instead

    Check which position the type occupies, input or output, before reasoning about the function.

  • Common mistake

    Treating the two shapes as unrelated tools

    Why it fails

    The source describes both shapes as belonging to one concept, so they are variations of the same idea.

    Do this instead

    Apply 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 fails

    Because the input is a type, the work concerns the structure or properties of that type rather than any particular runtime data.

    Do this instead

    Ask what property of the type matters, not what value the program holds at a given moment.

Practice Tracing Type Functions

MEDIUM

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.

Related concepts

More concepts starting with F