如何编写一个接受长度小于3的Vect的Idris函数

时间:2018-03-09 11:49:08

标签: idris dependent-type

Idris 1.2.0。我试图自动找到矢量长度小于3的证明。

f : {n : Nat} -> {auto prf: n < 3 = True} -> Vect n a -> ()
f v = ()

f' : {n : Nat} -> {auto prf: isJust (natToFin n 3) = True} -> Vect n a -> ()
f' v = ()

这两种类型检查,并与f {n=2} [1, 2}甚至f (the (Vect 2 Nat) [1, 2])一起使用,但当我将其称为f [1, 2]时,我得到了

When checking argument x to constructor Data.Vect.:::
    No such variable len

我还尝试了另一种方式:

g : {x : Fin 3} -> Vect (finToNat x) a -> ()
g v = ()

这也适用于g {x=2} [1, 2],但又失败了g [1, 2]

When checking an application of function Main.g:
    Type mismatch between
            Vect 2 Integer (Type of [1, 2])
    and
            Vect (finToNat x) Integer (Expected type)

    Specifically:
            Type mismatch between
                    2
            and
                    finToNat x

好吧,我猜这两个表达式在x未知时不会减少到相同的规范形式。

我不明白第一个错误。我怀疑它与[]语法重载有关。我做错了什么?

2 个答案:

答案 0 :(得分:2)

在尝试解决统一问题finToNat时,Idris不会尝试反转(内射)函数x来猜测finToNat x = 2的值。所以它只是卡住了。

在更一般的层面而不是在隐式参数的类型或证明搜索中推送计算,我将通过以下任一方式表示有界向量:

record BoundedVec (n : Nat) (a : Type) where
  size : Nat
  less : LTE size n
  vect : Vect size a

或者,关注Agda's standard library

data BoundedVec : (n : Nat) -> (a : Type) -> Type where
  Nil  : BoundedVec n a
  Cons : a -> BoundedVec n a -> BoundedVec (S n) a

答案 1 :(得分:0)

感谢gallais的洞察力。这是一个完整的例子:

-- idris -p contrib

import Data.BoundedList
import Data.Vect

-- a function that takes a list of at most 3 elements
f : BoundedList 3 a -> ()
f xs = ()

-- a shorter vector
v : Vect 2 Int
v = [1, 2]

-- convert the vector to a bounded list and weaken the bound
bounded : BoundedList 3 Int
bounded = weaken $ fromList $ toList v

-- call the function
answer : ()
answer = f bounded