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
1580f7db
Commit
1580f7db
authored
Aug 27, 2012
by
Adam Chlipala
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Proofreading pass through Chapter 8
parent
3d8c2800
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
39 additions
and
40 deletions
+39
-40
MoreDep.v
src/MoreDep.v
+39
-40
No files found.
src/MoreDep.v
View file @
1580f7db
...
@@ -65,41 +65,41 @@ Our [app] function could be typed in so-called%\index{stratified type systems}%
...
@@ -65,41 +65,41 @@ Our [app] function could be typed in so-called%\index{stratified type systems}%
(
*
EX
:
Implement
injection
from
normal
lists
*
)
(
*
EX
:
Implement
injection
from
normal
lists
*
)
(
*
begin
thide
*
)
(
*
begin
thide
*
)
Fixpoint
inject
(
ls
:
list
A
)
:
ilist
(
length
ls
)
:=
Fixpoint
inject
(
ls
:
list
A
)
:
ilist
(
length
ls
)
:=
match
ls
with
match
ls
with
|
nil
=>
Nil
|
nil
=>
Nil
|
h
::
t
=>
Cons
h
(
inject
t
)
|
h
::
t
=>
Cons
h
(
inject
t
)
end
.
end
.
(
**
We
can
define
an
inverse
conversion
and
prove
that
it
really
is
an
inverse
.
*
)
(
**
We
can
define
an
inverse
conversion
and
prove
that
it
really
is
an
inverse
.
*
)
Fixpoint
unject
n
(
ls
:
ilist
n
)
:
list
A
:=
Fixpoint
unject
n
(
ls
:
ilist
n
)
:
list
A
:=
match
ls
with
match
ls
with
|
Nil
=>
nil
|
Nil
=>
nil
|
Cons
_
h
t
=>
h
::
unject
t
|
Cons
_
h
t
=>
h
::
unject
t
end
.
end
.
Theorem
inject_inverse
:
forall
ls
,
unject
(
inject
ls
)
=
ls
.
Theorem
inject_inverse
:
forall
ls
,
unject
(
inject
ls
)
=
ls
.
induction
ls
;
crush
.
induction
ls
;
crush
.
Qed
.
Qed
.
(
*
end
thide
*
)
(
*
end
thide
*
)
(
*
EX
:
Implement
statically
checked
"car"
/
"hd"
*
)
(
*
EX
:
Implement
statically
checked
"car"
/
"hd"
*
)
(
**
Now
let
us
attempt
a
function
that
is
surprisingly
tricky
to
write
.
In
ML
,
the
list
head
function
raises
an
exception
when
passed
an
empty
list
.
With
length
-
indexed
lists
,
we
can
rule
out
such
invalid
calls
statically
,
and
here
is
a
first
attempt
at
doing
so
.
We
write
[
???
]
as
a
placeholder
for
a
term
that
we
do
not
know
how
to
write
,
not
for
any
real
Coq
notation
like
those
introduced
two
chapters
ago
.
(
**
Now
let
us
attempt
a
function
that
is
surprisingly
tricky
to
write
.
In
ML
,
the
list
head
function
raises
an
exception
when
passed
an
empty
list
.
With
length
-
indexed
lists
,
we
can
rule
out
such
invalid
calls
statically
,
and
here
is
a
first
attempt
at
doing
so
.
We
write
[
???
]
as
a
placeholder
for
a
term
that
we
do
not
know
how
to
write
,
not
for
any
real
Coq
notation
like
those
introduced
two
chapters
ago
.
[[
[[
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
match
ls
with
match
ls
with
|
Nil
=>
???
|
Nil
=>
???
|
Cons
_
h
_
=>
h
|
Cons
_
h
_
=>
h
end
.
end
.
]]
]]
It
is
not
clear
what
to
write
for
the
[
Nil
]
case
,
so
we
are
stuck
before
we
even
turn
our
function
over
to
the
type
checker
.
We
could
try
omitting
the
[
Nil
]
case
:
It
is
not
clear
what
to
write
for
the
[
Nil
]
case
,
so
we
are
stuck
before
we
even
turn
our
function
over
to
the
type
checker
.
We
could
try
omitting
the
[
Nil
]
case
:
[[
[[
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
match
ls
with
match
ls
with
|
Cons
_
h
_
=>
h
|
Cons
_
h
_
=>
h
end
.
end
.
]]
]]
<<
<<
...
@@ -109,10 +109,10 @@ Error: Non exhaustive pattern-matching: no clause found for pattern Nil
...
@@ -109,10 +109,10 @@ Error: Non exhaustive pattern-matching: no clause found for pattern Nil
Unlike
in
ML
,
we
cannot
use
inexhaustive
pattern
matching
,
because
there
is
no
conception
of
a
<<
Match
>>
exception
to
be
thrown
.
In
fact
,
recent
versions
of
Coq
_
do_
allow
this
,
by
implicit
translation
to
a
[
match
]
that
considers
all
constructors
.
It
is
educational
to
discover
that
encoding
ourselves
directly
.
We
might
try
using
an
[
in
]
clause
somehow
.
Unlike
in
ML
,
we
cannot
use
inexhaustive
pattern
matching
,
because
there
is
no
conception
of
a
<<
Match
>>
exception
to
be
thrown
.
In
fact
,
recent
versions
of
Coq
_
do_
allow
this
,
by
implicit
translation
to
a
[
match
]
that
considers
all
constructors
.
It
is
educational
to
discover
that
encoding
ourselves
directly
.
We
might
try
using
an
[
in
]
clause
somehow
.
[[
[[
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
match
ls
in
(
ilist
(
S
n
))
with
match
ls
in
(
ilist
(
S
n
))
with
|
Cons
_
h
_
=>
h
|
Cons
_
h
_
=>
h
end
.
end
.
]]
]]
<<
<<
...
@@ -124,13 +124,13 @@ In this and other cases, we feel like we want [in] clauses with type family argu
...
@@ -124,13 +124,13 @@ In this and other cases, we feel like we want [in] clauses with type family argu
Our
final
,
working
attempt
at
[
hd
]
uses
an
auxiliary
function
and
a
surprising
[
return
]
annotation
.
*
)
Our
final
,
working
attempt
at
[
hd
]
uses
an
auxiliary
function
and
a
surprising
[
return
]
annotation
.
*
)
(
*
begin
thide
*
)
(
*
begin
thide
*
)
Definition
hd
'
n
(
ls
:
ilist
n
)
:=
Definition
hd
'
n
(
ls
:
ilist
n
)
:=
match
ls
in
(
ilist
n
)
return
(
match
n
with
O
=>
unit
|
S
_
=>
A
end
)
with
match
ls
in
(
ilist
n
)
return
(
match
n
with
O
=>
unit
|
S
_
=>
A
end
)
with
|
Nil
=>
tt
|
Nil
=>
tt
|
Cons
_
h
_
=>
h
|
Cons
_
h
_
=>
h
end
.
end
.
Check
hd
'
.
Check
hd
'
.
(
**
%
\
vspace
{-
.15
in
}%
[[
(
**
%
\
vspace
{-
.15
in
}%
[[
hd
'
hd
'
:
forall
n
:
nat
,
ilist
n
->
match
n
with
:
forall
n
:
nat
,
ilist
n
->
match
n
with
...
@@ -140,7 +140,7 @@ hd'
...
@@ -140,7 +140,7 @@ hd'
]]
]]
*
)
*
)
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
hd
'
ls
.
Definition
hd
n
(
ls
:
ilist
(
S
n
))
:
A
:=
hd
'
ls
.
(
*
end
thide
*
)
(
*
end
thide
*
)
End
ilist
.
End
ilist
.
...
@@ -280,7 +280,7 @@ Definition pairOut t (e : exp t) :=
...
@@ -280,7 +280,7 @@ Definition pairOut t (e : exp t) :=
(
**
There
is
one
important
subtlety
in
this
definition
.
Coq
allows
us
to
use
convenient
ML
-
style
pattern
matching
notation
,
but
,
internally
and
in
proofs
,
we
see
that
patterns
are
expanded
out
completely
,
matching
one
level
of
inductive
structure
at
a
time
.
Thus
,
the
default
case
in
the
[
match
]
above
expands
out
to
one
case
for
each
constructor
of
[
exp
]
besides
[
Pair
]
,
and
the
underscore
in
[
pairOutDefault
_
]
is
resolved
differently
in
each
case
.
From
an
ML
or
Haskell
programmer
'
s
perspective
,
what
we
have
here
is
type
inference
determining
which
code
is
run
(
returning
either
[
None
]
or
[
tt
])
,
which
goes
beyond
what
is
possible
with
type
inference
guiding
parametric
polymorphism
in
Hindley
-
Milner
languages
%
\
index
{
Hindley
-
Milner
}%,
but
is
similar
to
what
goes
on
with
Haskell
type
classes
%
\
index
{
type
classes
}%.
(
**
There
is
one
important
subtlety
in
this
definition
.
Coq
allows
us
to
use
convenient
ML
-
style
pattern
matching
notation
,
but
,
internally
and
in
proofs
,
we
see
that
patterns
are
expanded
out
completely
,
matching
one
level
of
inductive
structure
at
a
time
.
Thus
,
the
default
case
in
the
[
match
]
above
expands
out
to
one
case
for
each
constructor
of
[
exp
]
besides
[
Pair
]
,
and
the
underscore
in
[
pairOutDefault
_
]
is
resolved
differently
in
each
case
.
From
an
ML
or
Haskell
programmer
'
s
perspective
,
what
we
have
here
is
type
inference
determining
which
code
is
run
(
returning
either
[
None
]
or
[
tt
])
,
which
goes
beyond
what
is
possible
with
type
inference
guiding
parametric
polymorphism
in
Hindley
-
Milner
languages
%
\
index
{
Hindley
-
Milner
}%,
but
is
similar
to
what
goes
on
with
Haskell
type
classes
%
\
index
{
type
classes
}%.
With
[
pairOut
]
available
,
we
can
write
[
cfold
]
in
a
straightforward
way
.
There
are
really
no
surprises
beyond
that
Coq
verifies
that
this
code
has
such
an
expressive
type
,
given
the
small
annotation
burden
.
In
some
places
,
we
see
that
Coq
'
s
[
match
]
annotation
inference
is
too
smart
for
its
own
good
,
and
we
have
to
turn
that
inference
with
explicit
[
return
]
clauses
.
*
)
With
[
pairOut
]
available
,
we
can
write
[
cfold
]
in
a
straightforward
way
.
There
are
really
no
surprises
beyond
that
Coq
verifies
that
this
code
has
such
an
expressive
type
,
given
the
small
annotation
burden
.
In
some
places
,
we
see
that
Coq
'
s
[
match
]
annotation
inference
is
too
smart
for
its
own
good
,
and
we
have
to
turn
that
inference
off
with
explicit
[
return
]
clauses
.
*
)
Fixpoint
cfold
t
(
e
:
exp
t
)
:
exp
t
:=
Fixpoint
cfold
t
(
e
:
exp
t
)
:
exp
t
:=
match
e
with
match
e
with
...
@@ -367,7 +367,7 @@ Theorem cfold_correct : forall t (e : exp t), expDenote e = expDenote (cfold e).
...
@@ -367,7 +367,7 @@ Theorem cfold_correct : forall t (e : exp t), expDenote e = expDenote (cfold e).
]]
]]
We
would
like
to
do
a
case
analysis
on
[
cfold
e1
]
,
and
we
attempt
t
hat
in
the
way
that
has
worked
so
far
.
We
would
like
to
do
a
case
analysis
on
[
cfold
e1
]
,
and
we
attempt
t
o
do
so
in
the
way
that
has
worked
so
far
.
[[
[[
destruct
(
cfold
e1
)
.
destruct
(
cfold
e1
)
.
]]
]]
...
@@ -759,7 +759,7 @@ Section insert.
...
@@ -759,7 +759,7 @@ Section insert.
End
present
.
End
present
.
End
insert
.
End
insert
.
(
**
We
can
generate
executable
OCaml
code
with
the
command
%
\
index
{
Vernacular
commands
!
Recursive
Extraction
}%
[
Recursive
Extraction
insert
]
,
which
also
automatically
outputs
the
OCaml
versions
of
all
of
[
insert
]
'
s
dependencies
.
In
our
previous
extractions
,
we
wound
up
with
clean
OCaml
code
.
Here
,
we
find
uses
of
%
\
index
{
Obj
.
magic
}%<<
Obj
.
magic
>>,
OCaml
'
s
unsafe
cast
operator
for
tweaking
the
apparent
type
of
an
expression
in
an
arbitrary
way
.
Casts
appear
for
this
example
because
the
return
type
of
[
insert
]
depends
on
the
_
value_
of
the
function
'
s
argument
,
a
pattern
which
OCaml
cannot
handle
.
Since
Coq
'
s
type
system
is
much
more
expressive
than
OCaml
'
s
,
such
casts
are
unavoidable
in
general
.
Since
the
OCaml
type
-
checker
is
no
longer
checking
full
safety
of
programs
,
we
must
rely
on
Coq
'
s
extractor
to
use
casts
only
in
provably
safe
ways
.
*
)
(
**
We
can
generate
executable
OCaml
code
with
the
command
%
\
index
{
Vernacular
commands
!
Recursive
Extraction
}%
[
Recursive
Extraction
insert
]
,
which
also
automatically
outputs
the
OCaml
versions
of
all
of
[
insert
]
'
s
dependencies
.
In
our
previous
extractions
,
we
wound
up
with
clean
OCaml
code
.
Here
,
we
find
uses
of
%
\
index
{
Obj
.
magic
}%<<
Obj
.
magic
>>,
OCaml
'
s
unsafe
cast
operator
for
tweaking
the
apparent
type
of
an
expression
in
an
arbitrary
way
.
Casts
appear
for
this
example
because
the
return
type
of
[
insert
]
depends
on
the
_
value_
of
the
function
'
s
argument
,
a
pattern
that
OCaml
cannot
handle
.
Since
Coq
'
s
type
system
is
much
more
expressive
than
OCaml
'
s
,
such
casts
are
unavoidable
in
general
.
Since
the
OCaml
type
-
checker
is
no
longer
checking
full
safety
of
programs
,
we
must
rely
on
Coq
'
s
extractor
to
use
casts
only
in
provably
safe
ways
.
*
)
(
*
begin
hide
*
)
(
*
begin
hide
*
)
Recursive
Extraction
insert
.
Recursive
Extraction
insert
.
...
@@ -799,7 +799,7 @@ Inductive regexp : (string -> Prop) -> Set :=
...
@@ -799,7 +799,7 @@ Inductive regexp : (string -> Prop) -> Set :=
User
error
:
Large
non
-
propositional
inductive
types
must
be
in
Type
User
error
:
Large
non
-
propositional
inductive
types
must
be
in
Type
>>
>>
What
is
a
%
\
index
{
large
inductive
types
}%
large
inductive
type
?
In
Coq
,
it
is
an
inductive
type
that
has
a
constructor
which
quantifies
over
some
type
of
type
[
Type
]
.
We
have
not
worked
with
[
Type
]
very
much
to
this
point
.
Every
term
of
CIC
has
a
type
,
including
[
Set
]
and
[
Prop
]
,
which
are
assigned
type
[
Type
]
.
The
type
[
string
->
Prop
]
from
the
failed
definition
also
has
type
[
Type
]
.
What
is
a
%
\
index
{
large
inductive
types
}%
large
inductive
type
?
In
Coq
,
it
is
an
inductive
type
that
has
a
constructor
that
quantifies
over
some
type
of
type
[
Type
]
.
We
have
not
worked
with
[
Type
]
very
much
to
this
point
.
Every
term
of
CIC
has
a
type
,
including
[
Set
]
and
[
Prop
]
,
which
are
assigned
type
[
Type
]
.
The
type
[
string
->
Prop
]
from
the
failed
definition
also
has
type
[
Type
]
.
It
turns
out
that
allowing
large
inductive
types
in
[
Set
]
leads
to
contradictions
when
combined
with
certain
kinds
of
classical
logic
reasoning
.
Thus
,
by
default
,
such
types
are
ruled
out
.
There
is
a
simple
fix
for
our
[
regexp
]
definition
,
which
is
to
place
our
new
type
in
[
Type
]
.
While
fixing
the
problem
,
we
also
expand
the
list
of
constructors
to
cover
the
remaining
regular
expression
operators
.
*
)
It
turns
out
that
allowing
large
inductive
types
in
[
Set
]
leads
to
contradictions
when
combined
with
certain
kinds
of
classical
logic
reasoning
.
Thus
,
by
default
,
such
types
are
ruled
out
.
There
is
a
simple
fix
for
our
[
regexp
]
definition
,
which
is
to
place
our
new
type
in
[
Type
]
.
While
fixing
the
problem
,
we
also
expand
the
list
of
constructors
to
cover
the
remaining
regular
expression
operators
.
*
)
...
@@ -915,7 +915,6 @@ Section split.
...
@@ -915,7 +915,6 @@ Section split.
(
P1_dec
(
substring
0
n
s
)
(
P1_dec
(
substring
0
n
s
)
&&
P2_dec
(
substring
n
(
length
s
-
n
)
s
))
&&
P2_dec
(
substring
n
(
length
s
-
n
)
s
))
||
F
n
'
_
||
F
n
'
_
]]
]]
The
[
split
]
function
itself
is
trivial
to
implement
in
terms
of
[
split
'
]
.
We
just
ask
[
split
'
]
to
begin
its
search
with
[
n
=
length
s
]
.
*
)
The
[
split
]
function
itself
is
trivial
to
implement
in
terms
of
[
split
'
]
.
We
just
ask
[
split
'
]
to
begin
its
search
with
[
n
=
length
s
]
.
*
)
...
@@ -1098,7 +1097,7 @@ Section dec_star.
...
@@ -1098,7 +1097,7 @@ Section dec_star.
Section
dec_star
''
.
Section
dec_star
''
.
Variable
n
:
nat
.
Variable
n
:
nat
.
(
**
[
n
]
is
the
length
of
the
prefix
of
[
s
]
that
we
have
already
processed
.
*
)
(
**
Variable
[
n
]
is
the
length
of
the
prefix
of
[
s
]
that
we
have
already
processed
.
*
)
Variable
P
'
:
string
->
Prop
.
Variable
P
'
:
string
->
Prop
.
Variable
P
'_
dec
:
forall
n
'
:
nat
,
n
'
>
n
Variable
P
'_
dec
:
forall
n
'
:
nat
,
n
'
>
n
...
@@ -1224,7 +1223,7 @@ Eval hnf in matches a_b "aa".
...
@@ -1224,7 +1223,7 @@ Eval hnf in matches a_b "aa".
Eval
hnf
in
matches
a_b
"b"
.
Eval
hnf
in
matches
a_b
"b"
.
(
*
end
hide
*
)
(
*
end
hide
*
)
(
**
Many
regular
expression
matching
problems
are
easy
to
test
.
The
reader
may
run
each
of
the
following
queries
to
verify
that
it
gives
the
correct
answer
.
We
use
evaluation
strategy
%
\
index
{
tactics
!
hnf
}%
[
hnf
]
to
reduce
each
term
to
%
\
index
{
head
-
normal
form
}%
_
head
-
normal
form_
,
where
the
datatype
constructor
used
to
build
its
value
is
known
.
*
)
(
**
Many
regular
expression
matching
problems
are
easy
to
test
.
The
reader
may
run
each
of
the
following
queries
to
verify
that
it
gives
the
correct
answer
.
We
use
evaluation
strategy
%
\
index
{
tactics
!
hnf
}%
[
hnf
]
to
reduce
each
term
to
%
\
index
{
head
-
normal
form
}%
_
head
-
normal
form_
,
where
the
datatype
constructor
used
to
build
its
value
is
known
.
(
Further
reduction
would
involve
wasteful
simplification
of
proof
terms
justifying
the
answers
of
our
procedures
.
)
*
)
Example
a_star
:=
Star
(
Char
"a"
%
char
)
.
Example
a_star
:=
Star
(
Char
"a"
%
char
)
.
Eval
hnf
in
matches
a_star
""
.
Eval
hnf
in
matches
a_star
""
.
...
...
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