我正在尝试学习一些模板Haskell。 作为练习,我写了一个函数,可以生成诸如isLeft和isLeft东西(受此问题的启发)。 这是我谦虚的尝试:
isA connam = do ConE nam <- connam nn <- newName "p" lamE [varP nn] $ caseE (varE nn) [ match (conP nam [wildP]) ( normalB [| True |] ) [], match wildP ( normalB [| False |] ) [] ]问题是它只适用于一个参数的构造函数。 罪魁祸首是conP nam [wildP]模式。 理想情况下,它应该看起来像conP nam (replicate (numArgs nam) wildP) ,其中numArgs是一个函数,返回构造函数的参数个数。 但是,我怎么写这样的功能呢? 我想我需要访问相关的数据声明,但我不知道如何。
这里还有一个关于这个相同功能的问题 。
I'm trying to learn some Template Haskell. As an exercise, I wrote a function that can generate things like isLeft and isRight (inspired by this question). Here's my humble attempt:
isA connam = do ConE nam <- connam nn <- newName "p" lamE [varP nn] $ caseE (varE nn) [ match (conP nam [wildP]) ( normalB [| True |] ) [], match wildP ( normalB [| False |] ) [] ]The problem is that it only works with one-argument constructors. The culprit is the conP nam [wildP] pattern. Ideally, it should look like conP nam (replicate (numArgs nam) wildP), where numArgs is a function returning the number of arguments of the constructor. But how do I write such a function? I imagine I need to access the relevant data declaration, but I have no idea how to.
There is another question about this very same function here.
最满意答案
虽然您可以使用reify并检查类型以确定数据构造函数的arity,但使用记录模式生成与arity无关的代码要容易得多:
isFoo :: Bar -> Bool isFoo p = case p of (Foo {}) -> True -- Valid no matter what the arity of Foo is _ -> False这可以通过用代码中的recP替换conP来完成。
isA connam = do ConE nam <- connam nn <- newName "p" lamE [varP nn] $ caseE (varE nn) [ match (recP nam []) ( normalB [| True |] ) [], match wildP ( normalB [| False |] ) [] ]While you could use reify and examine the type to determine the arity of the data constructor, it's much easier to generate arity-independent code using a record pattern:
isFoo :: Bar -> Bool isFoo p = case p of (Foo {}) -> True -- Valid no matter what the arity of Foo is _ -> FalseThis can be done by replacing conP with recP in your code.
isA connam = do ConE nam <- connam nn <- newName "p" lamE [varP nn] $ caseE (varE nn) [ match (recP nam []) ( normalB [| True |] ) [], match wildP ( normalB [| False |] ) [] ]更多推荐
发布评论