Reputation: 119847
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.
Upvotes: 3
Views: 294
Reputation: 139830
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 |] ) []
]
Upvotes: 7