从外部函数返回依赖对
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
表达式中定义的 n
与 n
中的 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
有三个参数(t
,n
,和一个 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
相同。)
我有以下 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
表达式中定义的 n
与 n
中的 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
有三个参数(t
,n
,和一个 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
相同。)