我正在尝试将一小部分PureScript代码移植到Idris,在这种情况下,可能会应用依赖类型,并偶然遇到在依赖类型中使用case
的情况。
因为这是有效的(简体):
data ValidInvoice3 : (ft : FeeType) -> Type where
MkVI3 : ValidInvoice3 ft
以下为什么不输入检查?
-- BROKEN
data ValidInvoice4 : (ft : FeeType) -> Type where
MkVI4 : case ft of
FeeMarkupHidden => ValidInvoice4 ft -- simplified;
FeeExplicit => ValidInvoice4 ft -- more elaborate example below
如果您有兴趣为什么我要研究此内容:这里有一些更详细的示例代码:
module DependentWithCase
data FeeType = FeeMarkupHidden | FeeExplicit
data Fee : (ft : FeeType) -> Type where
MkFee : Fee ft -- simplified
data ValidArticle : (ft : FeeType) -> Type where
MkVA : ValidArticle ft -- simplified
这里是如何使用case
表达式成功确定“发票”的依存类型并在FeeType上建立索引,以确定是否将费用作为显式参数添加(在实际代码中,在这种情况下,“文章”类型具有一个“标记”部分,我在这里将其遗漏了;通过这种方式,我可以确定“标记”仅开票一次):
data ValidInvoice : (ft : FeeType) -> Type where
MkVI : ValidArticle ft ->
case ft of FeeMarkupHidden => Unit; FeeExplicit => Fee ft;
->
ValidInvoice ft
因此,您会看到发票数据类型(在实际代码中,商品类型也是如此)取决于费用类型。
但是,与其使用隐藏在构造函数内部的case表达式,不如让它看起来像这种类型的同义词(当然,它没有构造函数;但这实质上是它在PureScript代码中的读取方式,但是而是使用具有单独构造函数的sum类型而不是此处的依赖类型(在FeeType上建立索引)。这对我来说更具可读性(尤其是在实际代码中)。
ValidInvoice2 : (ft : FeeType) -> Type
ValidInvoice2 FeeMarkupHidden = ValidArticle FeeMarkupHidden -> Unit -> ValidInvoice2 FeeMarkupHidden
ValidInvoice2 FeeExplicit = ValidArticle FeeExplicit -> Fee FeeExplicit -> ValidInvoice2 FeeExplicit
那么ValidInvoice4
为什么不进行类型检查?我写错了吗?还是期望有些东西行不通?
答案 0 :(得分:0)
看来Idris并未注意到case语句的任何一个分支都会导致ValidInvoice4
。它还不会在相似位置评估函数。您几乎总是可以做一些稍有不同的事情,但是得到相同的结果。
考虑您要完成的工作,我建议将Fee
设为索引FeeType
的{{1}}-简化整个过程:
Maybe