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]) ( normal开发者_如何学编程B [| 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.
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 |] ) []
]
精彩评论