Hi! I am very new to Coq and I’m trying to prove a simple matrix transpose function. As part of my matrix transpose, I have a function called maphd
, which takes the head of each item in a list of lists, and returns the result as a new list.
I have:
Fixpoint maphd (l: list (list A)): (list A):=
match l with
| nil => nil
| a :: t => (hd a):: (maphd t)
end.
However, this fails with the error:
In environment
A : Type
maphd : list (list A) -> list A
l : list (list A)
a : list A
t : list (list A)
The term "maphd t" has type "list A"
while it is expected to have type "list (list (list A) -> list A)".
I don’t know how to put this right!
I should add, I have a separate hd
function to get the head of a list, which compiles fine.
What is the type of your hd
function?
The following seems to work:
Fixpoint maphd (hd : list A -> A) (l: list (list A)) : (list A):=
match l with
| nil => nil
| a :: t => (hd a):: (maphd hd t)
end.
Here is my hd
function:
Definition hd (default:A) (l:list A): A :=
match l with
| [] => default
| x :: _ => x
end.
so hd
needs a default
argument.
You should probably do the same in maphd
. What behavior are you waiting for in maphd [ [] ]
?
The type of “hd” is not what you think it is
Gaëtan Gilbert
So you mean if I supply an empty list of lists? I would expect an empty list back, I guess.
Ah ok. So where have I gone wrong?
First you cannot imagine have a hd
function from list A
to A
for an arbitrary A
. This is why you need a default
argument in the definition of hd
. This leads to hd : A -> list A -> A
.
Then in your code for maphd
, the term hd a
should be hd default a : A
for some appropriate default
element of type A
. So the most direct modification of your maphd
would be:
Fixpoint maphd (default : A) (l: list (list A)) : (list A):=
match l with
| nil => nil
| a :: t => (hd default a):: (maphd default t)
end.
which leads to maphd default [ [] ] = [ default ]
.
Now if you want maphd
to throw away empty lists, you have to say so in the code:
Fixpoint maphd (l: list (list A)) : (list A):=
match l with
| nil => nil
| nil :: t => maphd t
| (a :: r) :: t => (hd a (a::r)):: (maphd t)
end.
(here choosing a
as default
argument) but then the call to hd
can be inlined to get:
Fixpoint maphd (l: list (list A)) : (list A):=
match l with
| nil => nil
| nil :: t => maphd t
| (a :: r) :: t => a :: (maphd t)
end.
Thank you so much! I’ll need to take some time to parse and understand your reply, but it looks immensely helpful.
1 Like