Lectures onType Theory
ch:coinduction: ch:coinduction
appendix sectionsolutions

ch:coinduction: ch:coinduction

Exercise 85.1.

Take state 2, output the state itself, transition Boolean negation, and initial state tt: alternate:=corec2(2,λx.x,not,tt). The state iterates at depths 0 through 4 are tt,ff,tt,ff,tt, respectively. Applying the output function, which is the identity, gives the same five observations.

Exercise 85.2.

The complete clauses are head(zipWith(f,s,t))=f(head(s))(head(t)),tail(zipWith(f,s,t))=zipWith(f,tail(s),tail(t)). Compile them with state Stream(A)×Stream(B) and maps o(u,v):=f(head(u))(head(v)),d(u,v):=(tail(u),tail(v)). The corecursor’s head and tail equations reduce judgmentally to the two clauses. Deleting the tail clause leaves tail(zipWith(f,s,t)) uncovered, so the copattern definition is incomplete.

Exercise 85.4.

Use the proof-relevant relation L(r,t):=zipWith(f,r,t),R(r,t):=zipWith(f,t,r),B(u,v):=r:Stream(A)t:Stream(A)(IdStream(A)(u,L(r,t))×IdStream(A)(v,R(r,t))). Eliminate the two identities carried by a witness (r,t,,). The head obligation is exactly c(head(r))(head(t)). The tails reduce to zipWith(f,tail(r),tail(t)),zipWith(f,tail(t),tail(r)), which belong to B with witnesses tail(r),tail(t). Thus B is a bisimulation, and stream coinduction gives the required observational equality.

Exercise 85.3.

Let s be the constant-zero stream. Let t be generated from Boolean state with output 0 at ff, output 1 at tt, negating transition, and initial state ff. Then both heads are 0, so B(s,t) holds, but their depth-one observations are 0 and 1. The proposed relation has no closure witness B(tail(s),tail(t)); this is precisely the second premise of definition 85.12.

Exercise 85.5.

Use the proof-relevant relation B(u,v):=r:Stream(A)(IdStream(A)(u,map(λx.x,r))×IdStream(A)(v,r)). After eliminating the two identities carried by a witness (r,,), the heads calculate as head(map(λx.x,r))(λx.x)(head(r))head(r). The tails are related with witness tail(r) because tail(map(λx.x,r))map(λx.x,tail(r)). Coinduction yields map(λx.x,s)As.

Exercise 85.6.

Use state (n,a):N×N, output a, transition (n,a)(suc(n),a+suc(n)), and initial state (0,0). The equivalent copattern clauses are head(T(n,a))=a,tail(T(n,a))=T(suc(n),a+suc(n)). Their compilation is exactly that pair-state corecursor. Starting from (0,0), the states have second components 0,1,3,6,10,15, so these are the first six observations. To compare a separately named copattern definition with the compiled corecursor, relate the two results at every state (n,a). Their heads are both a and their tails are related at (suc(n),a+suc(n)); coinduction proves observational equality.

Exercise 85.7.

The zero clauses compile with state 1, constant output 0, and the identity transition, so both are accepted instances of definition 85.9. Put s:=nats:=iterate(suc,0). Its head equation is judgmental, while its tail relation is observational: head(s)0,tail(s)Nmap(suc,s). For the second equation, relate, for every n, iterate(suc,suc(n))andmap(suc,iterate(suc,n)). Their heads both compute to suc(n); their tails have the same relation at suc(n) by the iterate-tail and map-tail rules. Coinduction proves the displayed observational equality at n=0. Written as a recursive clause, its recursive occurrence is nested under map rather than being the complete result of the matched tail clause, so the selected syntactic guard rejects it.

For the finite observations, first prove by induction on n that nth(n,map(f,r))=f(nth(n,r)). The zero case is Map-head. The successor case uses Map-tail and the induction hypothesis at tail(r). More directly, induction on n with the iterate computation rules gives nth(0,s)0,nth(suc(n),s)nth(n,iterate(suc,1))=theorem85.3sucn(1)=induction on nsuc(n). Thus s has observations 0,1,2,. The observational tail equation and these calculations prove productivity of the example without turning stream observational equality into identity or claiming completeness of the guard checker.

Search the book

Type to search the local edition.