在Idris中列出和类型元素的惯用法

时间:2017-08-16 14:32:13

标签: dependent-type idris

我有一个表示算术运算符的和类型:

data Operator = Add | Substract | Multiply | Divide

我试图为它编写解析器。为此,我需要一份所有运营商的详尽清单。

在Haskell中,我会使用以下StackOverflow问题中建议的deriving (Enum, Bounded)Getting a list of all possible data type values in Haskell

不幸的是,Issue #19所建议的伊德里斯似乎并没有这样的机制。大卫·克里斯蒂安森正在就这个问题进行一些正在进行的工作,希望将来情况有所改善:david-christiansen/derive-all-the-instances

来自Scala,我习惯手动列出元素,所以我很自然地想出了以下内容:

Operators : Vect 4 Operator
Operators = [Add, Substract, Multiply, Divide]

为了确保Operators包含所有元素,我添加了以下证明:

total
opInOps : Elem op Operators
opInOps {op = Add} = Here
opInOps {op = Substract} = There Here
opInOps {op = Multiply} = There (There Here)
opInOps {op = Divide} = There (There (There Here))

因此,如果我将一个元素添加到Operator而不将其添加到Operators,那么整体检查程序会抱怨:

Parsers.opInOps is not total as there are missing cases

它完成了工作,但它是很多样板。 我错过了什么?有没有更好的方法呢?

1 个答案:

答案 0 :(得分:3)

可以选择使用elaborator reflection等语言的这种功能来获取所有构造函数的列表。

这是解决这个特殊问题的一种非常愚蠢的方法(我发布这个是因为目前的文档非常缺乏):

%language ElabReflection

data Operator = Add | Subtract | Multiply | Divide

constrsOfOperator : Elab ()
constrsOfOperator = 
  do (MkDatatype _ _ _ constrs) <- lookupDatatypeExact `{Operator}
     loop $ map fst constrs

  where loop : List TTName -> Elab ()
        loop [] =
          do fill `([] : List Operator); solve
        loop (c :: cs) =
          do [x, xs] <- apply `(List.(::) : Operator -> List Operator -> List Operator) [False, False]
             solve
             focus x; fill (Var c); solve
             focus xs
             loop cs

allOperators : List Operator
allOperators = %runElab constrsOfOperator

一对评论:

  1. 似乎要解决类似结构的任何归纳数据类型的问题,需要通过Elaborator Reflection: Extending Idris in Idris论文。
  2. 也许pruviloj库可能会更容易解决这个问题。