从外部函数返回依赖对

Returning a dependent pair from a foreign function

我有以下 Chez 支持文件:

(define list-copy-with-length (xs)
  (cons (length xs) (list-copy xs)))

我有这个 Idris 文件:

%foreign "scheme,chez:list-copy-with-length"
prim__listToVect : List t -> (Nat, Vect n t)

listToVect : List t -> (n ** Vect n t)
listToVect ls =
  let (n, vs) = prim__listToVect ls
  in MkDPair n vs

自然地,此代码的类型检查失败,因为编译器不知道 let 表达式中定义的 nn 中的 n 相同=31=] listToVect.

类型

我尝试了一些猜测来使用 believe_me 来解决这个问题,但我无法弄清楚。是否可以定义这样的函数?正确的方法是什么,而不会产生大量的递归重新计算长度的运行时成本(如 Data.Vect.filter)?

这是一个这样的猜测:

listToVect : {t : _} -> {n : _} -> List t -> (n ** Vect n t)
listToVect ls =
  let (n', vs) = prim__listToVect ls
      itsEqualDamnit : Equal n' n = believe_me ()
  in rewrite itsEqualDamnit in MkDPair n vs

理想情况下,无论如何我都想完全避免拆包,因为(至少在 Chez 后端),对和依赖对都以相同的方式表示为 cons 单元。

believe_me 已经是一个不安全的转换。只是...施放 Vect?

%foreign "scheme,chez:list-copy-with-length"
prim__listToVect : List t -> (Nat, Vect n t)

listToVect : List t -> (n ** Vect n t)
listToVect ls =
  let (n, vs) = prim__listToVect {n = 0} ls
  in  MkDPair n (believe_me vs)

你的 Scheme 代码是错误的:define 的语法不是那样的,list-copy-to-vect 需要三个参数,因为 prim__listToVect 有三个参数(tn,和一个 List t)。请注意,我在 Idris 侧为 n 传递了一个虚拟变量。

(define (list-copy-with-length t n xs) (cons (length xs) (list-copy xs)))

通过配对此 Scheme 定义,您可以更加直接

(define (idris-prim-listToVect t xs) (cons (length xs) (list-copy xs)))

有了这个伊德里斯

%foreign "scheme,chez:idris-prim-listToVect"
prim__listToVect : List t -> (Nat, List t)

listToVect : List t -> (n ** Vect n t)
listToVect xs = believe_me (prim__listToVect xs)

(这是有效的,因为正如您所指出的,DPair 表示与普通对相同,List 表示与 Vect 相同。)