I'm trying to implement something like a functional queue in Idris, but which carries the number of elements in the type - such as Queue ty n m (n+m)
where n
is the number of elements in one Vect n ty
, m
is the elements in a second Vect m ty
, and (n+m)
is the total elements.
The problem is, I'm running into problems with applying rewrite rules when manipulating these sizes as implicit arguments:
module Queue
import Data.Vect as V
data Queue : Type -> Nat -> Nat -> Nat -> Type where
mkQueue : (front : V.Vect n ty)
-> (back : V.Vect m ty)
-> Queue ty n m (n + m)
%name Queue queue
top : Queue ty n m (S k) -> ty
top {n = S j} {m} {k = j + m} (mkQueue front back) =
V.head front
top {n = Z} {m = S j} {k = j} (mkQueue front back) =
V.head $ V.reverse back
bottom : Queue ty n m (S k) -> ty
bottom {m = S j} {n} {k = n + j} (mkQueue front back) =
?some_rewrite_1 (V.head back)
bottom {m = Z} {n = S j} {k = j} (mkQueue front back) =
?some_rewrite_2 (V.head $ V.reverse front)
top
works but bottom
does not. It would appear that I somehow need to supply plusZeroRightNeutral
and plusRightSuccRight
rewrites, but I'm not sure where to put those, or whether there might be another option. Here are the error messages:
Error on first line of bottom
:
Type mismatch between
Queue ty n (S j) (n + S j) (Type of mkQueue front back)
and
Queue ty n (S j) (S (n + j)) (Expected type)
Specifically:
Type mismatch between
plus n (S j)
and
S (n + j)
Error on second line of bottom
:
Type mismatch between
Queue ty (S j) 0 (S j + 0) (Type of mkQueue front back)
and
Queue ty (S j) 0 (S j) (Expected type)
Specifically:
Type mismatch between
plus (S j) 0
and
S j
The individual sizes tell me when I need to rotate the two Vect
s, and the overall size tells me when I have an empty vs. non-empty Queue
, so I do want to track all the information if possible.
One possible way of solving this problem is to destruct
n
as well. This time Idris understands that the last argument is not zero, which it is basically complaining about:As a side note, I'd suggest to make the
top
function total: