35Implementation
Extract a nested request payload
Problem
payloadOrZero receives a Packet, which is either a Data packet carrying a
Request struct or a Flush packet with no payload. It must return the
request's payload for Data and 8'h00 for Flush. The starter ignores its
argument and always returns 8'h00, so the public run shows 00 for both
packets instead of a5 for the data packet.
Edit only the body of payloadOrZero. Keep both type declarations, the function
signature, and mkTop unchanged. Do not unpack the packet into raw bits; the
exercise is about pattern matching on the typed shape.
Read and predict
- Read
Packetfirst. It has two alternatives, and onlyDatacarries a value. - Read
Request. The value insideDatahas two fields,channelandpayload, and only one of them matters for the result. - Read the two calls in
mkTop: one passestagged Data requestwith payload8'ha5, the other passestagged Flush.
Before pressing Run, predict both lines for the starter. Both read 00,
and only the data line is wrong. The code compiles because returning a constant
is type-correct; this is a behavior defect.
Make the repair
Replace the constant return with a case ... matches that has one arm per
alternative. Build the Data arm from the outside in: match the tag, then the
struct, and only then introduce a name for the field you need. Fields that do
not affect the result can be left out of the struct pattern.
Run again and check that the data line now shows a5 while the flush line
stays 00. Then explain why the payload name can only exist inside the Data
arm: outside it, there is no request to take a field from.
Completion contract
- Every
Datapacket returns its ownpayload, including a payload of zero and anychannelvalue. - Every
Flushpacket returns8'h00. - The function uses pattern matching on the tagged union and the nested struct.
- Returning
8'ha5for the visible sample does not satisfy other payloads.
Progressive hints
Hint 1: match the shape of the type
Patterns nest the same way the data does. The outer pattern checks which tag is active; an inner struct pattern can then bind one field of the carried value.
Hint 2: start the data arm
The first arm begins with the Data tag and is followed by a pattern for the
Request struct, not by a plain variable that holds the whole struct.
Hint 3: bind only what you return
Inside the struct pattern, name only the field that owns the result, using a
pattern variable. The Flush arm needs no binding at all.
Transfer experiment
On paper, change the function so it returns the two-bit channel instead,
widened to the same result type. Identify which parts of the pattern stay the
same and which binding moves.