What decides whether a payroll routine's placeholder is pinned at or above a type rather than at or below it?
answer
- read the body before the signature
- calls on the value versus values handed in
- at or below grants calls
- at or above grants acceptance
- empty call list needs no limit
basics
~20 sWhat the body does with the value. If it calls that type's own operations, pin the placeholder at or below the type; if it only hands values of that type in somewhere, pin it at or above.
solid answer
~40 sThe two directions grant opposite powers, so read the body before writing the signature. A totalling routine calls an amount operation on each pay component, so the element placeholder is pinned **at or below** the pay-component supertype — every admissible argument then declares that operation. A posting routine never inspects what it produces; it hands finished ledger lines into a destination it was given, so the destination's element placeholder is pinned **at or above** the ledger-line type — anything at least that general will accept a ledger line. The mistake is to pick from a remembered mnemonic instead of the call list. Note also that languages differ in where the at-or-above form may be written: some allow it on the declaration, others only on a qualified use of a parameterized type.
code
pseudocode · 11 lines// The body calls an operation ON the value: pin at or below
function totalOf<T at or below PayComponent>(items: list of T) -> Amount
var sum = zeroAmount
for each item in items
sum = sum + item.minorUnits()
return sum
// The body hands values IN: pin at or above
function postTotals<S at or above LedgerLine>(sink: Sink of S, lines: list of LedgerLine)
for each line in lines
sink.accept(line) // a LedgerLine is acceptable wherever an S isgo deeper
Learn the two directions as a pair of opposite powers: at or below a type lets you call that type's operations, at or above it lets you hand values of that type in. Do not expect one to do both.
Be able to derive the direction live: list what the body does to the value, list what it hands in, and read the limit straight off those two lists. Say why an unused limit is a cost.
Demonstrate that you notice the third case — a body that wants both powers — and that your fix is to split the parameters or name the type exactly, rather than to pick a direction and cast around it.
The judgment to own is signature shape across a codebase: routines that read and routines that write are usually separate responsibilities, and a limit that wants both directions is often telling you the routine is doing two jobs.
## Two directions, opposite powers A limit on a placeholder pins it relative to a named type, and there are only two directions to pin it in. They are not stylistic variants of each other; each one buys a power the other refuses. | Limit direction | Reads as | The body may | The caller may supply | |---|---|---|---| | At or below a named type | "every argument is this type or something more specific" | Call every operation the named type declares | That type and everything beneath it | | At or above a named type | "every argument is this type or something more general" | Hand values of the named type in, because any such value is acceptable | That type and everything above it | | Unrestricted | "any type at all" | Only hold, move and return the value | Anything | The asymmetry is the whole point. An at-or-below limit is a **guarantee about what the value can do**, so it licenses calls. An at-or-above limit is a **guarantee about what the value will accept**, so it licenses handing something in. Neither grants the other. ## Read the body, not the signature The practical procedure is a short one, and it works before the signature exists: - List every operation the body performs **on** a value of the placeholder type. If the list is non-empty, you need an at-or-below limit naming a type that declares all of them. - List every value the body **produces** and needs to hand into something typed by the placeholder. If that list is non-empty, you need an at-or-above limit naming the type of what you produce. - If both lists are empty, the placeholder needs no limit at all — it is only being carried through, and adding a limit narrows callers for nothing. That ordering matters because the mnemonic route — memorising a phrase and applying it to the shape of the signature — fails on exactly the cases where it matters, and leaves the candidate unable to explain the answer they gave. ## The payroll pair Consider a payroll run in two halves. The first half totals. It walks a list of pay components and asks each one for its amount. The operation is performed **on** the value, so the element placeholder is pinned at or below the pay-component supertype: a list of bonuses, a list of overtime lines, or a mixed list of the supertype itself all satisfy it, and the body's call is safe for every one. The second half posts. It builds ledger lines and hands them into a destination the caller supplied. It never asks a posted value anything. So the destination's element placeholder is pinned at or above the ledger-line type: a destination that accepts ledger lines works, and so does a more general destination — a general ledger sink that accepts any posted record, or one that accepts absolutely anything. Every one of those will accept a ledger line, which is all the body needs. A useful sanity check on the second case: the wider the destination, the *more* callers are admitted, which feels backwards until you notice that generality is being demanded of the destination, not of the value. ## When the body wants both Sometimes the body both calls a value's operations and hands new values of that type in. No single limit direction gives both powers, because each direction refuses what the other grants. The honest signatures are: 1. **Name the type exactly.** Give up the placeholder for that position and accept the concrete type, losing the ability to track the caller's specific type. 2. **Split the parameters.** Take a source pinned at or below the type to read from, and a destination pinned at or above it to write into. The payroll run is naturally this shape already — components in, ledger lines out — and separating them is usually a sign the two responsibilities were distinct all along. ## A note on where the form may be written Languages genuinely differ here, and an interviewer may probe it. Some type systems allow both directions to be written on the placeholder's own declaration. Others allow only the at-or-below direction there, and express the at-or-above direction on a *use* of a parameterized type instead. The reasoning above is unaffected — the question of which direction the body needs is answered the same way in both — but the place you write the answer moves. ## Where this stops One caution: deciding a direction from what the body does is not the same question as deciding it from where a type parameter *appears inside* a parameterized type. That second question, and the subtyping conclusions it supports, is a separate subject; here the input is the call list, and the output is a limit on one placeholder.
- If the body only stores the value and returns it later, which direction does it need?Neither. An unrestricted placeholder already lets the value be held, moved and returned, and it preserves the caller's own type through the call. Adding a limit here narrows who may call the routine and buys the body nothing it was going to use.
- Once the direction is settled, how do you choose which type to name in the limit?For an at-or-below limit, name the smallest type that declares every operation the body calls — anything larger excludes callers for free. For an at-or-above limit, name the exact type of the values the body produces; naming something more general would promise callers less than the body actually needs to hand in.
- Why is a mnemonic a poor substitute for reading the body?Because a mnemonic maps a remembered phrase onto the shape of a signature, and the shape can be right for reasons the candidate cannot state. Reading the call list gives the same answer plus the justification, and it still works on a signature whose shape the mnemonic never covered.
saying these in an interview costs you the question
- Says an at-or-above limit lets the body call the named type's operations
- Thinks the at-or-below direction is about writing values in
- Expects one limit direction to grant both calling and accepting
- Picks the direction from a memorised phrase without reading the call list
- Assumes a wider limit is always safer, ignoring what the body must call