12

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 I have to write $(isA [| Left |]) instead of the more intuitive isA Left. Is it possible to get rid of the ugly syntax? I can't seem to find the answer in the documentation.

The function only works with one-argument constructors, but this is for another question.

Community
  • 1
  • 1
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243

1 Answers1

11

The syntax is there for a reason; to inform the reader that there is compile-time magic going on here. You can only eliminate the $(...) when your splice is at the top level.

However, we can eliminate the [| ... |] and also make the code more type-safe by taking in a Name instead of an Exp:

isA nam = do
    nn <- newName "p"
    lamE [varP nn] $ caseE (varE nn) [
                       match (conP nam [wildP]) ( normalB [| True |] ) [],
                       match wildP ( normalB [| False |] ) [] 
                     ]

To use this, you'd write $(isA 'Left), which is a little easier on the eyes.

As a bonus, if you try giving it something other than a Name, you get a type error instead of an irrefutable pattern match error.

See also: Template Haskell Syntax

hammar
  • 138,522
  • 17
  • 304
  • 385
  • Thanks. I can definitely live with that. I remember reading somewhere that `$` is no longer necessary for splices, but I'm not sure in what context it was, or whether it can apply here. – n. m. could be an AI Aug 27 '11 at 12:46
  • @n.m. I just added that to my answer a moment ago :) I guess you were still viewing my original answer while writing your comment. – hammar Aug 27 '11 at 12:48
  • aha, so if I want `isA 'Left` to generate a declaration of a function named `isALeft` instead of the actual function, I can omit the $, right? – n. m. could be an AI Aug 27 '11 at 12:54