Idris中基于Fin而非Nat实现向量初始段函数的类型错误问题
Let's break down what's going wrong with your code and how to fix it step by step.
The Root Cause of the Type Error
Your original return type Vect n (p ** Vect (finToNat p) t) has a critical mismatch:
pis typed asFin n, which meansfinToNat pcan only produce values from0ton-1(sinceFin nrepresents natural numbers less thann).- But your function is trying to return initial segments of lengths
1throughn—including the full vector of lengthn. To get a segment length ofn, you needfinToNat p = n, which is impossible withp : Fin n. This is why the type checker rejects your code.
The Corrected Code
We need to adjust the return type to use Fin (S n) for p—this type allows p to take values from 0 to n, so finToNat p can cover all required segment lengths from 1 to n. Here's the fixed version:
vectorsInits : Vect n t -> Vect n (p : Fin (S n) ** Vect (finToNat p) t) vectorsInits Nil = Nil vectorsInits (x::xs) = ((FS FZ) ** (x::Nil)) :: map (\(p ** ys) => ((FS p) ** x::ys)) (vectorsInits xs)
Why This Works
Let's verify the type consistency for the recursive case:
- When processing
x::xs(a vector of lengthS len),vectorsInits xsreturns aVect len (p : Fin (S len) ** Vect (finToNat p) t). - The
mapfunction transforms each element(p ** ys)to(FS p ** x::ys):FS pconverts aFin (S len)toFin (S (S len)), which is exactlyFin (S n)(sincen = S len).x::yshas lengthS (finToNat p), which equalsfinToNat (FS p)—perfectly matching the vector length required by the dependent pair.
- The first element
((FS FZ) ** (x::Nil))hasp : Fin (S n)(sinceFS FZisFin (S (S len))) and a vector length of1, which isfinToNat (FS FZ).
All types now align correctly, satisfying the type checker.
Example Usage
For a vector [1,2,3] : Vect 3 Int, the function will return:
[ (FS FZ ** [1]), (FS (FS FZ) ** [1,2]), (FS (FS (FS FZ)) ** [1,2,3]) ]
Each element's p is a Fin 4 (since S n = 4), and finToNat p gives the exact length of the corresponding initial segment.
内容的提问来源于stack exchange,提问作者Robert Kirk

