Idris:为长度为Fin而非Nat

时间:2018-04-29 15:02:35

标签: idris

我正在尝试为向量编写初始段函数,它将向量的长度存储为Fin而不是Nat,如下所示:

vectorsInits : Vect n t -> Vect n (p ** Vect (finToNat p) t)
vectorsInits Nil = Nil
vectorsInits (x::xs) = ((FS FZ) ** (x::Nil)) :: map (\(p ** ys) => ((FS p) ** x::ys)) (vectorsInits xs)

但是这个定义不起作用,因为我得到以下类型错误:

When checking right hand side of vectorsInits with expected type

    Vect (S len) (p : Fin n ** Vect (finToNat p) t)

When checking argument pf to constructor Builtins.MkDPair:

    Type mismatch between

            Vect 1 t (Type of [x])

    and

            Vect (finToNat (FS FZ)) t (Expected type)

    Specifically:

            Type mismatch between

                    1

            and

                    finToNat (FS FZ)

但是finToNat的定义很清楚,finToNat(FS FZ)将等于1。即使我编写以下函数试图让idris意识到它们是平等的,我也会收到错误:

intproof : Vect 1 t -> Vect (finToNat (FS FZ)) t 
intproof x = x
...
vectorsInits (x::xs) = ((FS FZ) ** intproof (x::Nil)) :: map (\(p ** ys) => ((FS p) ** x::ys)) (vectorsInits xs)

给我错误:

When checking right hand side of vectorsInits with expected type
        Vect (S len) (p : Fin n ** Vect (finToNat p) t)
When checking argument pf to constructor Builtins.MkDPair:
    Type mismatch between
            Vect (finToNat (FS FZ)) t (Type of intproof [x])
    and
            (\p => Vect (finToNat p) t) (FS FZ) (Expected type)
    Specifically:
            Type mismatch between
                    1
            and
                    finToNat (FS FZ)
甚至写作:

intproof : Vect 1 t -> (\p => Vect (finToNat p) t) (FS FZ)
intproof x = x

得到与上面相同的错误

我有%默认总数,我在我文件的开头导入Data.Vect。

有没有办法迫使Idris认识到finToNat(FS FZ)等于1(即S Z))?

由于

1 个答案:

答案 0 :(得分:2)

你有一个问题:

vectorsInits : Vect n t -> Vect n (p ** Vect (finToNat p) t)

p的类型是什么?你没有给它,它实际上最终是

vectorsInits : Vect n t -> Vect n (p : Fin m ** Vect (finToNat p) t)

也就是说,在数据旁边运行的Fin的类型与输入完全无关。那是不对的。它应该(至少)

vectorsInits : Vect n t -> Vect n (p : Fin n ** Vect (finToNat p) t)

然而,这也不太正确。应该发生的事情是FinFZlast计数,直到输出为止,但您当前的实现并没有这样做。如果你改变它,你会发现每个输出向量的长度都大于索引:

vectorsInits : Vect n t -> Vect n (p : Fin n ** Vect (S (finToNat p)) t)
vectorsInits [] = []
vectorsInits (x :: xs) = (FZ ** [x]) :: map (\(idx ** ixs) => (FS idx ** x :: ixs)) (vectorsInits xs)

或者,您可以在输出的开头添加[](毕竟,[]是每个列表的前缀),从而获得一个服从身份{{1}的版本(省略了一些错误):

index n (vectorInits xs) = take n xs