Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
C
cpdt
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
research
cpdt
Commits
9a908b9e
Commit
9a908b9e
authored
Oct 23, 2011
by
Adam Chlipala
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished pass over Coinductive
parent
f84e7b02
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
119 additions
and
50 deletions
+119
-50
cpdt.bib
latex/cpdt.bib
+7
-0
Coinductive.v
src/Coinductive.v
+104
-50
updates.rss
staging/updates.rss
+8
-0
No files found.
latex/cpdt.bib
View file @
9a908b9e
...
@@ -252,3 +252,10 @@
...
@@ -252,3 +252,10 @@
number = "0221",
number = "0221",
institution = "INRIA",
institution = "INRIA",
}
}
@inproceedings{BigStep,
author = {Xavier Leroy and Herv\'e Grall},
title = {Coinductive big-step operational semantics},
year = {2006},
booktitle = {Proceedings of the 15th European Symposium on Programming}
}
src/Coinductive.v
View file @
9a908b9e
...
@@ -257,7 +257,7 @@ unguarded recursive call in "ones_eq"
...
@@ -257,7 +257,7 @@ unguarded recursive call in "ones_eq"
Via
the
Curry
-
Howard
correspondence
,
the
same
guardedness
condition
applies
to
our
co
-
inductive
proofs
as
to
our
co
-
inductive
data
structures
.
We
should
be
grateful
that
this
proof
is
rejected
,
because
,
if
it
were
not
,
the
same
proof
structure
could
be
used
to
prove
any
co
-
inductive
theorem
vacuously
,
by
direct
appeal
to
itself
!
Via
the
Curry
-
Howard
correspondence
,
the
same
guardedness
condition
applies
to
our
co
-
inductive
proofs
as
to
our
co
-
inductive
data
structures
.
We
should
be
grateful
that
this
proof
is
rejected
,
because
,
if
it
were
not
,
the
same
proof
structure
could
be
used
to
prove
any
co
-
inductive
theorem
vacuously
,
by
direct
appeal
to
itself
!
Thinking
about
how
Coq
would
generate
a
proof
term
from
the
proof
script
above
,
we
see
that
the
problem
is
that
we
are
violating
the
guardedness
condition
.
During
our
proofs
,
Coq
can
help
us
check
whether
we
have
yet
gone
wrong
in
this
way
.
We
can
run
the
command
[
Guarded
]
in
any
context
to
see
if
it
is
possible
to
finish
the
proof
in
a
way
that
will
yield
a
properly
guarded
proof
term
.%
\
index
{
Vernacular
command
!
Guarded
}%
Thinking
about
how
Coq
would
generate
a
proof
term
from
the
proof
script
above
,
we
see
that
the
problem
is
that
we
are
violating
the
guardedness
condition
.
During
our
proofs
,
Coq
can
help
us
check
whether
we
have
yet
gone
wrong
in
this
way
.
We
can
run
the
command
[
Guarded
]
in
any
context
to
see
if
it
is
possible
to
finish
the
proof
in
a
way
that
will
yield
a
properly
guarded
proof
term
.%
\
index
{
Vernacular
command
s
!
Guarded
}%
[[
[[
Guarded
.
Guarded
.
]]
]]
...
@@ -517,73 +517,127 @@ Qed.
...
@@ -517,73 +517,127 @@ Qed.
(
**
*
Simple
Modeling
of
Non
-
Terminating
Programs
*
)
(
**
*
Simple
Modeling
of
Non
-
Terminating
Programs
*
)
(
**
We
close
the
chapter
with
a
quick
motivating
example
for
more
complex
uses
of
co
-
inductive
types
.
We
will
define
a
co
-
inductive
semantics
for
a
simple
assembly
language
and
use
that
semantics
to
prove
that
assembly
programs
always
run
forever
.
This
basic
technique
can
be
combined
with
typing
judgments
for
more
advanced
languages
,
where
some
ill
-
typed
programs
can
go
wrong
,
but
no
well
-
typed
programs
go
wrong
.
(
**
We
close
the
chapter
with
a
quick
motivating
example
for
more
complex
uses
of
co
-
inductive
types
.
We
will
define
a
co
-
inductive
semantics
for
a
simple
imperative
programming
language
and
use
that
semantics
to
prove
the
correctness
of
a
trivial
optimization
that
removes
spurious
additions
by
0.
We
follow
the
technique
of
%
\
index
{
co
-
inductive
big
-
step
operational
semantics
}
\
emph
{%
#
<
i
>
#
co
-
inductive
big
-
step
operational
semantics
#
</
i
>
#
%}~
\
cite
{
BigStep
}%
.
We
define
suggestive
synonyms
for
[
nat
]
,
for
cases
where
we
use
natural
numbers
as
registers
or
program
labels
.
That
is
,
we
consider
our
idealized
machine
to
have
infinitely
many
registers
and
infinitely
many
code
addresse
s
.
*
)
We
define
a
suggestive
synonym
for
[
nat
]
,
as
we
will
consider
programs
with
infinitely
many
variables
,
represented
as
[
nat
]
s
.
*
)
Definition
reg
:=
nat
.
Definition
var
:=
nat
.
Definition
label
:=
nat
.
(
**
Our
instructions
are
loading
of
a
constant
into
a
register
,
copying
from
one
register
to
another
,
unconditional
jump
,
and
conditional
jump
based
on
whether
the
value
in
a
register
is
not
zero
.
*
)
(
**
We
define
a
type
[
vars
]
of
maps
from
variables
to
values
.
To
define
a
function
[
set
]
for
setting
a
variable
'
s
value
in
a
map
,
we
import
the
[
Arith
]
module
from
Coq
'
s
standard
library
,
and
we
use
its
function
[
beq_nat
]
for
comparing
natural
numbers
.
*
)
Inductive
instr
:
Set
:=
Definition
vars
:=
var
->
nat
.
|
Imm
:
reg
->
nat
->
instr
Require
Import
Arith
.
|
Copy
:
reg
->
reg
->
instr
Definition
set
(
vs
:
vars
)
(
v
:
var
)
(
n
:
nat
)
:
vars
:=
|
Jmp
:
label
->
instr
fun
v
'
=>
if
beq_nat
v
v
'
then
n
else
vs
v
'
.
|
Jnz
:
reg
->
label
->
instr
.
(
**
We
define
a
type
[
regs
]
of
maps
from
registers
to
values
.
To
define
a
function
[
set
]
for
setting
a
register
'
s
value
in
a
map
,
we
import
the
[
Arith
]
module
from
Coq
'
s
standard
library
,
and
we
use
its
function
[
beq_nat
]
for
comparing
natural
numbers
.
*
)
(
**
We
define
a
simple
arithmetic
expression
language
with
variables
,
and
we
give
it
a
semantics
via
an
interpreter
.
*
)
Definition
regs
:=
reg
->
nat
.
Inductive
exp
:
Set
:=
Require
Import
Arith
.
|
Const
:
nat
->
exp
Definition
set
(
rs
:
regs
)
(
r
:
reg
)
(
v
:
nat
)
:
regs
:=
|
Var
:
var
->
exp
fun
r
'
=>
if
beq_nat
r
r
'
then
v
else
rs
r
'
.
|
Plus
:
exp
->
exp
->
exp
.
Fixpoint
evalExp
(
vs
:
vars
)
(
e
:
exp
)
:
nat
:=
match
e
with
|
Const
n
=>
n
|
Var
v
=>
vs
v
|
Plus
e1
e2
=>
evalExp
vs
e1
+
evalExp
vs
e2
end
.
(
**
An
inductive
[
exec
]
judgment
captures
the
effect
of
an
instruction
on
the
program
counter
and
register
bank
.
*
)
(
**
Finally
,
we
define
a
language
of
commands
.
It
includes
variable
assignment
,
sequencing
,
and
a
%
\
texttt
{%
#
<
tt
>
#
while
#
</
tt
>
#
%}%
form
that
repeats
as
long
as
its
test
expression
evaluates
to
a
nonzero
value
.
*
)
Inductive
exec
:
label
->
regs
->
instr
->
label
->
regs
->
Prop
:=
Inductive
cmd
:
Set
:=
|
E_Imm
:
forall
pc
rs
r
n
,
exec
pc
rs
(
Imm
r
n
)
(
S
pc
)
(
set
rs
r
n
)
|
Assign
:
var
->
exp
->
cmd
|
E_Copy
:
forall
pc
rs
r1
r2
,
exec
pc
rs
(
Copy
r1
r2
)
(
S
pc
)
(
set
rs
r1
(
rs
r2
))
|
Seq
:
cmd
->
cmd
->
cmd
|
E_Jmp
:
forall
pc
rs
pc
'
,
exec
pc
rs
(
Jmp
pc
'
)
pc
'
rs
|
While
:
exp
->
cmd
->
cmd
.
|
E_JnzF
:
forall
pc
rs
r
pc
'
,
rs
r
=
0
->
exec
pc
rs
(
Jnz
r
pc
'
)
(
S
pc
)
rs
|
E_JnzT
:
forall
pc
rs
r
pc
'
n
,
rs
r
=
S
n
->
exec
pc
rs
(
Jnz
r
pc
'
)
pc
'
rs
.
(
**
We
prove
that
[
exec
]
represents
a
total
function
.
In
our
proof
script
,
we
use
a
[
match
]
tactic
with
a
[
context
]
pattern
.
This
particular
example
finds
an
occurrence
of
a
pattern
[
Jnz
?
r
_
]
anywhere
in
the
current
subgoal
'
s
conclusion
.
We
use
a
Coq
library
tactic
[
case_eq
]
to
do
case
analysis
on
whether
the
current
value
[
rs
r
]
of
the
register
[
r
]
is
zero
or
not
.
[
case_eq
]
differs
from
[
destruct
]
in
saving
an
equality
relating
the
old
variable
to
the
new
form
we
deduce
for
it
.
*
)
(
**
We
could
define
an
inductive
relation
to
characterize
the
results
of
command
evaluation
.
However
,
such
a
relation
would
not
capture
%
\
emph
{%
#
<
i
>
#
nonterminating
#
</
i
>
#
%}%
executions
.
With
a
co
-
inductive
relation
,
we
can
capture
both
cases
.
The
parameters
of
the
relation
are
an
initial
state
,
a
command
,
and
a
final
state
.
A
program
that
does
not
terminate
in
a
particular
initial
state
is
related
to
%
\
emph
{%
#
<
i
>
#
any
#
</
i
>
#
%}%
final
state
.
*
)
Lemma
exec_total
:
forall
pc
rs
i
,
CoInductive
evalCmd
:
vars
->
cmd
->
vars
->
Prop
:=
exists
pc
'
,
exists
rs
'
,
exec
pc
rs
i
pc
'
rs
'
.
|
EvalAssign
:
forall
vs
v
e
,
evalCmd
vs
(
Assign
v
e
)
(
set
vs
v
(
evalExp
vs
e
))
Hint
Constructors
exec
.
|
EvalSeq
:
forall
vs1
vs2
vs3
c1
c2
,
evalCmd
vs1
c1
vs2
->
evalCmd
vs2
c2
vs3
->
evalCmd
vs1
(
Seq
c1
c2
)
vs3
|
EvalWhileFalse
:
forall
vs
e
c
,
evalExp
vs
e
=
0
->
evalCmd
vs
(
While
e
c
)
vs
|
EvalWhileTrue
:
forall
vs1
vs2
vs3
e
c
,
evalExp
vs1
e
<>
0
->
evalCmd
vs1
c
vs2
->
evalCmd
vs2
(
While
e
c
)
vs3
->
evalCmd
vs1
(
While
e
c
)
vs3
.
destruct
i
;
crush
;
eauto
;
(
**
Having
learned
our
lesson
in
the
last
section
,
before
proceeding
,
we
build
a
co
-
induction
principle
for
[
evalCmd
]
.
*
)
match
goal
with
|
[
|-
context
[
Jnz
?
r
_
]
]
=>
case_eq
(
rs
r
)
end
;
eauto
.
Qed
.
(
**
We
are
ready
to
define
a
co
-
inductive
judgment
capturing
the
idea
that
a
program
runs
forever
.
We
define
the
judgment
in
terms
of
a
program
[
prog
]
,
represented
as
a
function
mapping
each
label
to
the
instruction
found
there
.
That
is
,
to
simplify
the
proof
,
we
consider
only
infinitely
long
programs
.
*
)
Section
evalCmd_coind
.
Variable
R
:
vars
->
cmd
->
vars
->
Prop
.
Section
safe
.
Hypothesis
AssignCase
:
forall
vs1
vs2
v
e
,
R
vs1
(
Assign
v
e
)
vs2
Variable
prog
:
label
->
instr
.
->
vs2
=
set
vs1
v
(
evalExp
vs1
e
)
.
CoInductive
safe
:
label
->
regs
->
Prop
:=
Hypothesis
SeqCase
:
forall
vs1
vs3
c1
c2
,
R
vs1
(
Seq
c1
c2
)
vs3
|
Step
:
forall
pc
r
pc
'
r
'
,
->
exists
vs2
,
R
vs1
c1
vs2
/
\
R
vs2
c2
vs3
.
exec
pc
r
(
prog
pc
)
pc
'
r
'
->
safe
pc
'
r
'
->
safe
pc
r
.
(
**
Now
we
can
prove
that
any
starting
address
and
register
bank
lead
to
safe
infinite
execution
.
Recall
that
proofs
of
existentially
quantified
formulas
are
all
built
with
a
single
constructor
of
the
inductive
type
[
ex
]
.
This
means
that
we
can
use
[
destruct
]
to
%
``
%
#
"#open up#"
#
%
''
%
such
proofs
.
In
the
proof
below
,
we
want
to
perform
this
opening
up
on
an
appropriate
use
of
the
[
exec_total
]
lemma
.
This
lemma
'
s
conclusion
begins
with
two
existential
quantifiers
,
so
we
want
to
tell
[
destruct
]
that
it
should
not
stop
at
the
first
quantifier
.
We
accomplish
our
goal
by
using
an
%
\
textit
{%
#
<
i
>
#
intro
pattern
#
</
i
>
#
%}%
with
[
destruct
]
.
Consult
the
Coq
manual
for
the
details
of
intro
patterns
;
the
specific
pattern
[[
?
[
?
?
]]]
that
we
use
here
accomplishes
our
goal
of
destructing
both
quantifiers
at
once
.
*
)
Hypothesis
WhileCase
:
forall
vs1
vs3
e
c
,
R
vs1
(
While
e
c
)
vs3
->
(
evalExp
vs1
e
=
0
/
\
vs3
=
vs1
)
Theorem
always_safe
:
forall
pc
rs
,
\
/
exists
vs2
,
evalExp
vs1
e
<>
0
/
\
R
vs1
c
vs2
/
\
R
vs2
(
While
e
c
)
vs3
.
safe
pc
rs
.
cofix
;
intros
;
(
**
The
proof
is
routine
.
We
make
use
of
a
form
of
%
\
index
{
tactics
!
destruct
}%
[
destruct
]
that
takes
an
%
\
index
{
intro
pattern
}
\
emph
{%
#
<
i
>
#
intro
pattern
#
</
i
>
#
%}%
in
an
[
as
]
clause
.
These
patterns
control
how
deeply
we
break
apart
the
components
of
an
inductive
value
,
and
we
refer
the
reader
to
the
Coq
manual
for
more
details
.
*
)
destruct
(
exec_total
pc
rs
(
prog
pc
))
as
[
?
[
?
?
]]
;
econstructor
;
eauto
.
Theorem
evalCmd_coind
:
forall
vs1
c
vs2
,
R
vs1
c
vs2
->
evalCmd
vs1
c
vs2
.
cofix
;
intros
;
destruct
c
.
rewrite
(
AssignCase
H
)
;
constructor
.
destruct
(
SeqCase
H
)
as
[
?
[
?
?
]]
;
econstructor
;
eauto
.
destruct
(
WhileCase
H
)
as
[[
?
?
]
|
[
?
[
?
[
?
?
]]]]
;
subst
;
[
econstructor
|
econstructor
4
]
;
eauto
.
Qed
.
Qed
.
End
safe
.
End
evalCmd_coind
.
(
**
Now
that
we
have
a
co
-
induction
principle
,
we
should
use
it
to
prove
something
!
Our
example
is
a
trivial
program
optimizer
that
finds
places
to
replace
[
0
+
e
]
with
[
e
]
.
*
)
Fixpoint
optExp
(
e
:
exp
)
:
exp
:=
match
e
with
|
Plus
(
Const
0
)
e
=>
optExp
e
|
Plus
e1
e2
=>
Plus
(
optExp
e1
)
(
optExp
e2
)
|
_
=>
e
end
.
(
**
If
we
print
the
proof
term
that
was
generated
,
we
can
verify
that
the
proof
is
structured
as
a
[
cofix
]
,
with
each
co
-
recursive
call
properly
guarded
.
*
)
Fixpoint
optCmd
(
c
:
cmd
)
:
cmd
:=
match
c
with
|
Assign
v
e
=>
Assign
v
(
optExp
e
)
|
Seq
c1
c2
=>
Seq
(
optCmd
c1
)
(
optCmd
c2
)
|
While
e
c
=>
While
(
optExp
e
)
(
optCmd
c
)
end
.
(
**
Before
proving
correctness
of
[
optCmd
]
,
we
prove
a
lemma
about
[
optExp
]
.
This
is
where
we
have
to
do
the
most
work
,
choosing
pattern
match
opportunities
automatically
.
*
)
(
*
begin
thide
*
)
Lemma
optExp_correct
:
forall
vs
e
,
evalExp
vs
(
optExp
e
)
=
evalExp
vs
e
.
induction
e
;
crush
;
repeat
(
match
goal
with
|
[
|-
context
[
match
?
E
with
Const
_
=>
_
|
Var
_
=>
_
|
Plus
_
_
=>
_
end
]
]
=>
destruct
E
|
[
|-
context
[
match
?
E
with
O
=>
_
|
S
_
=>
_
end
]
]
=>
destruct
E
end
;
crush
)
.
Qed
.
Hint
Rewrite
optExp_correct
:
cpdt
.
(
**
The
final
theorem
is
easy
to
establish
,
using
our
co
-
induction
principle
and
a
bit
of
Ltac
smarts
that
we
leave
unexplained
for
now
.
Curious
readers
can
consult
the
Coq
manual
,
or
wait
for
the
later
chapters
of
this
book
about
proof
automation
.
*
)
Theorem
optCmd_correct
:
forall
vs1
c
vs2
,
evalCmd
vs1
c
vs2
->
evalCmd
vs1
(
optCmd
c
)
vs2
.
intros
;
apply
(
evalCmd_coind
(
fun
vs1
c
'
vs2
=>
exists
c
,
evalCmd
vs1
c
vs2
/
\
c
'
=
optCmd
c
))
;
eauto
;
crush
;
match
goal
with
|
[
H
:
_
=
optCmd
?
E
|-
_
]
=>
destruct
E
;
simpl
in
*;
discriminate
||
injection
H
;
intros
;
subst
end
;
match
goal
with
|
[
H
:
evalCmd
_
_
_
|-
_
]
=>
((
inversion
H
;
[])
||
(
inversion
H
;
[
|
]))
;
subst
end
;
crush
;
eauto
10.
Qed
.
(
*
end
thide
*
)
Print
always_safe
.
(
**
In
this
form
,
the
theorem
tells
us
that
the
optimizer
preserves
observable
behavior
of
both
terminating
and
nonterminating
programs
,
but
we
did
not
have
to
do
more
work
than
for
the
case
of
terminating
programs
alone
.
We
merely
took
the
natural
inductive
definition
for
terminating
executions
,
made
it
co
-
inductive
,
and
applied
the
appropriate
co
-
induction
principle
.
Curious
readers
might
experiment
with
adding
command
constructs
like
%
\
texttt
{%
#
<
tt
>
#
if
#
</
tt
>
#
%}%;
the
same
proof
should
continue
working
,
after
the
co
-
induction
principle
is
extended
to
the
new
evaluation
rules
.
*
)
(
**
*
Exercises
*
)
(
**
*
Exercises
*
)
...
...
staging/updates.rss
View file @
9a908b9e
...
@@ -11,6 +11,14 @@
...
@@ -11,6 +11,14 @@
<webMaster>
adam@chlipala.net
</webMaster>
<webMaster>
adam@chlipala.net
</webMaster>
<docs>
http://blogs.law.harvard.edu/tech/rss
</docs>
<docs>
http://blogs.law.harvard.edu/tech/rss
</docs>
<item>
<title>
A pass through "Infinite Data and Proofs"
</title>
<pubDate>
Sun, 23 Oct 2011 14:47:55 EDT
</pubDate>
<link>
http://adam.chlipala.net/cpdt/
</link>
<author>
adamc@csail.mit.edu
</author>
<description>
I've added new discussion of co-induction principles and replaced the programming language semantics example.
</description>
</item>
<item>
<item>
<title>
A pass through "Universes and Axioms"
</title>
<title>
A pass through "Universes and Axioms"
</title>
<pubDate>
Wed, 19 Oct 2011 09:58:57 EDT
</pubDate>
<pubDate>
Wed, 19 Oct 2011 09:58:57 EDT
</pubDate>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment