如何模式匹配 Idris/Agda/Coq 中的多个值?

How to pattern match multiple values in Idris/Agda/Coq?

我想在我的 Expr 定义中捕获类型有效性,但在定义 Add 时出现问题,预计后面会跟 DecimalWhole 参数,但我不知道如何对它们进行模式匹配。以下是我的试验:

第一次试用:

data DataType = Text | Decimal | Whole

data Expr : DataType -> Type where
    Add : (Expr Decimal) -> (Expr Decimal) -> Expr Decimal
    Add : (Expr Whole) -> (Expr Whole) -> Expr Whole

二审:

data DataType = Text | Decimal | Whole

data Expr : DataType -> Type where
    Add : (Expr ty) -> (Expr ty) -> Expr ty

第三次审判:

data DataType = Text | Decimal | Whole

data Expr : DataType -> Type where
    Add : (Expr ty@(Decimal | Whole)) -> (Expr ty) -> Expr ty

在第一次试用中,我被告知无法定义 Add 两次。在第二次试验中,我不知道如何添加 ty 必须是 DecimalWhole 之一的约束。第三次试用使用了一些尚不支持的虚构语法..

您实际上需要对 ty 施加约束。一种通用的方法是

data Numeric : DataType -> Type where
  decimal-numeric : Numeric Decimal
  whole-numeric : Numeric Whole

data Expr : DataType -> Type where
  add : Numeric ty -> Expr ty -> Expr ty -> Expr ty

您可以通过使用 instance/default 参数作为 addNumeric ty 参数来使它更好用,具体取决于您使用的语言。 Numeric 类型究竟是什么取决于您。这里我使用了一个简单的依赖类型,但是你也可以考虑一个Haskell类型class实例的函数记录。

另一种方法是使用类型层次结构

data NumericType : Type where
  Whole, Decimal : NumericType

data DataType : Type where
  Numeric : NumericType -> DataType
  String : DataType

data Expr : DataType -> Type where
  Add : Expr (Numeric nty) -> Expr (Numeric nty) -> Expr (Numeric nty)
Coq 语法中的

Inductive DataType : Type := Text | Decimal | Whole.

Inductive Numeric : DataType -> Type :=
  decimal_numeric : Numeric Decimal
| whole_numeric : Numeric Whole.

Inductive Expr : DataType -> Type :=
  add ty : Numeric ty -> Expr ty -> Expr ty -> Expr ty.