I am relatively new to idris and dependent-types and I encountered the following problem - I created a custom data type similar to vectors:
infixr 1 :::
data TupleVect : Nat -> Nat -> Type -> Type where
Empty : TupleVect Z Z a
(:::) : (Vect o a, Vect p a) ->
TupleVect n m a ->
TupleVect (n+o) (m+p) a
exampleTupleVect : TupleVect 5 4 Int
exampleTupleVect = ([1,2], [1]) ::: ([3,4],[2,3]) ::: ([5], [4]) ::: Empty
It is inductively constructed by adding tuples of vectors and indexed by the sum of the vector lengths in each tuple position.
I tried to implement a map function for my data type:
tupleVectMap : ((Vect k a, Vect l a) -> (Vect k b, Vect l b)) ->
TupleVect n m a -> TupleVect n m b
tupleVectMap f Empty = Empty
tupleVectMap f (x ::: xs) = let fail = f x
in ?rest_of_definition
This yields the following type error:
|
20 | tupleVectMap f (x ::: xs) = let fail = f x
| ~~~~~~~~~~~~~~ ...
When checking right hand side of tupleVectMap with expected type
TupleVect (n + o) (m + p) b
Type mismatch between
(Vect o a, Vect p a)
and
(Vect k a, Vect l a)
It seems that the typechecker can't unify the lengths of the vectors in the extracted tuple x and the required lengths in the argument of f. However I don't understand why that is since k and l are just the type names indicating that f doesn't change the length of the given vectors.
I am even more perplexed since the following typechecks:
tupleVectMap' : TupleVect n m a -> TupleVect n m b
tupleVectMap' Empty = Empty
tupleVectMap' (x ::: xs) =
let nonfail = f x
in ?rest_of_definition
where
f : ((Vect k a, Vect l a) -> (Vect k b, Vect l b))
Here f has the exact same type signature. The only difference being that f is defined locally.