我有一个表示算术运算符的和类型:
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
它完成了工作,但它是很多样板。 我错过了什么?有没有更好的方法呢?
答案 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
一对评论: