functional-programming - Idris 中的“不可访问的模式变量”
问题描述
我遇到了一个问题,即 Idris 中的模式匹配给出“不可访问的模式变量”错误,即使我只是使用编译器来指导模式匹配。
这是我正在尝试做的一个例子。细节并不是非常重要,主要的是我有一些类似于向量的东西,除了它是通过向量索引之间的关系参数化的,而不是使用相等性。然后我得到了另一种定义关系的类型,其中一个变体是向量之间的关系 PC。(我的实际代码还有其他情况,我刚刚把它们删掉了)。
然后我试图通过在 PC 证明上进行模式匹配来定义一个函数“trans”。如果我执行“trans pf1 pf2 = ?foo”,那么它可以工作。但是,如果我区分大小写(使用编辑器命令来区分大小写),我会得到“nwhole 不是可访问的模式变量”。这对我来说似乎很奇怪,在一个类型检查的程序上执行编译器给定的大小写分割会产生一个没有的程序。而且,我不知道如何进行代码类型检查。
有谁知道这里发生了什么?这是一个错误,还是我的隐式参数/类型索引做错了什么?
module MinimalExample
data NNat = NNone | NZ | NSucc NNat
parameters (rel : NNat -> NNat -> Type )
data PreVec : Type -> NNat -> Type where
VNil : {elem : Type} -> {nindex : NNat} -> rel nindex NZ -> PreVec elem nindex
VCons : {elem : Type} -> {nindex : NNat} -> {ntail : NNat} -> elem -> PreVec elem ntail -> rel (NSucc ntail) nindex -> PreVec elem nindex
data PC : {tipe1 : Type} -> {tipe2 : Type} -> tipe1 -> tipe2 -> Type where
PCNone : {a : tipe1} -> {b : tipe2} -> PC a b
PCCons : {elemType : Type} -> {n1 : NNat} -> {n2 : NNat} -> {nwhole : NNat} ->
{t1 : PreVec (PC {tipe1 = NNat} {tipe2 = NNat} ) elemType n1} ->
{t2 : PreVec (PC {tipe1 = NNat} {tipe2 = NNat} ) elemType n2} ->
PC h1 h2 ->
PC t1 t2 ->
(pf1 : PC (NSucc n1) (NSucc nwhole)) ->
(pf2: PC (NSucc n2) (NSucc nwhole)) ->
PC (VCons PC {ntail=n1} {elem=elemType} h1 t1 pf1) (VCons PC {ntail=n2} {elem=elemType} h2 t2 pf2)
trans : {tx : Type} -> {ty : Type} -> {tz : Type} -> {x : tx} -> {y : ty} -> {z : tz} ->
PC x y -> PC y z -> PC x z
trans PCNone pf2 = ?trans_1
trans (PCCons y z pf1 x) pf2 = ?trans_2
解决方案
首先,大小写分离器相当笨拙,目前独立于类型检查器。它的主要作用是创建每个案例并询问类型检查器该分支是否有效。
我找到了一个显示类似问题的最小示例。
data PreVec : Nat -> Type where
VCons : PreVec n
data Bad : {tipe1 : Type} -> tipe1 -> Type where
MkBad : Bad VCons
data Good1 : PreVec n -> Type where
MkGood1 : Good1 VCons
data Bad2 : {tipe1: Type} -> tipe1 -> Type where
MkBad2 : {n: Nat} -> Bad2 (VCons {n})
以类似的方式使用这些会在 Bad 构造函数上产生错误,但会在好的构造函数上找到。
我不能说我完全理解这个问题,但它似乎主要与类型等隐式的解析顺序有关,它可能是一个编译器错误。基本上,隐式tipe1
取决于n
封装在构造函数本身中的变量。我的猜测是,类型中的隐式在构造函数打开之前被填充,所以这n
不在模式类型的范围内。
似乎有多个补丁可以修复它。如果变量tipe1(或tipe2)是显式而不是隐式的,那么使用_
无处不在会为您的示例正确合成类型。或者,将返回类型更改为:
PC (the (PreVec elemType (NSucc nwhole)) (VCons PC elemType (NSucc nwhole) n1 h1 pf1))
(VCons PC elemType (NSucc nwhole) n2 h2 pf2)
也成功了。不成功的一件事是将其他所有隐式更改为显式,它只与这些tipe1和tipe2有关。它们在构造函数中的每个实例都受到约束,因此类型本身没有问题。只有在执行模式匹配时才会出现这种情况。
推荐阅读
- javascript - 如何将侦听器添加到 JavaScript 创建的模板
- c# - Blazor Mono.Linker.LoadException
- kubernetes - 错误:验证失败:无法识别“”:版本“networking.k8s.io/v1beta1”中类型“Ingress”没有匹配项
- html-email - HTML 电子邮件模板是否应该使用表格元素进行布局?
- join - 在 CLI 上使用 bq 从 BigQuery 标准 SQL 连接表中打印出漂亮的值表?
- javascript - 从所有选中的复选框中获取 ID
- angular - 如何在离子框架中调用菜单切换承诺
- google-cloud-speech - Google 云平台上的音频是否可用于 Speech-To-Text?
- mysql - 计算mysql中项目的总价格
- strawberry-perl - 如何为 IIS 设置 Strawberry Perl v5.30 ISAPI 支持