Question

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.

Était-ce utile?

La solution

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
    _        -> False

This 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 |] ) [] 
                     ]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top