Idris依赖对:编译程序和REPL

时间:2018-09-06 14:26:36

标签: idris dependent-type

在Idris中使用依赖对进行练习时,我在编译的程序和REPL之间遇到了意外的行为差异。以下是我正在测试的数据类型:

(a : Type ** b : Type ** Arrow a b)

应该表示类型a和类型b之间的某种关系。给定上述情况的一个例子,我想提取该类型的“证明”一词。我可以使用DPair.snd $ DPair.snd <some-instance>从REPL进行此操作,一切正常。但是,如果我尝试创建一个函数:

unwrap : (a ** b ** Arrow a b) -> Arrow a b
unwrap x = DPair.snd $ DPair.snd x

该程序将编译,但是当我尝试调用它时将失败。返回的错误消息是

(input): No such variable b

有人遇到过这种情况或知道解决方案吗?

2 个答案:

答案 0 :(得分:0)

您想实现的目标是不可能的。如果查看unwrap : (a1 : Type ** b1 : Type ** Arrow a b) -> Arrow a b的类型,则会发现它使用的数据类型与(a : Type ** b : Type ** Arrow a b)不同。这是因为参数ab是预先量化的-设置了结果类型(这也是REPL情况的区别;您不必绑定到参数)。因此,:set showimplicit

Main.unwrap : {b : Type} -> {a : Type} ->
              (a1 : Type ** b1 : Type ** Main.Arrow a b) ->
              Main.Arrow a b

这就是依赖对的问题,您不能轻易限制它们。看看Vect.filter : (elem -> Bool) -> Vect len elem -> (p : Nat ** Vect p elem)-如果我们有一个像unwrap : (p : Nat ** Vect p elem) -> Vect p elem这样的函数,那么我们就不需要依赖对了。

相反,调用unwrap的函数将需要检查p,然后相应地处理Vect。遗憾的是,我们无法轻松检查类型(至少如果要对所有类型进行概括)。所以最好的选择是:不要在这里使用依赖类型。

答案 1 :(得分:0)

我意识到我要迟到一年半了,但是...这绝对有可能!您只需要记住类型a ** P只是DPair a (\x => P a)的语法糖;在后一种形式中,没有什么特别的事情发生,因此您可以像期望的那样使用ab。我们还可以通过在标准库中键入DPair.snd来获得洞察力:

Idris> :t DPair.snd
snd : (x : DPair a P) -> P (fst x)

因此,要从我们的货币对中提取a值,我们只需在该货币对上调用fst。多么直观! (fst本身只是类型DPair a P -> a)。要获取b值(这是我们对第二部分的第一个值),我们在最外面的对上调用fst . snd。因此,您的函数应如下所示:

unwrap : (x : DPair a (DPair b . Arrow)) -> Arrow (fst x) (snd $ fst x)
unwrap x = snd (snd x)

(或等价的:)

unwrap : (x : DPair a (\theA => DPair b (\theB => Arrow theA theB))) -> ...

无论出于何种原因,unwrap = DPair.snd . DPair.snd都不起作用...但这并不是一个太大的问题。