Search code examples
haskelltemplate-haskell

TemplateHaskell not installed... then it is


I'm writing a program in Haskell, and it involves a lot of parentheses. So to clear up that ugly mess, I use the $ operator a couple of times to make it easier to read. For example:

longFunc arg1 (anotherFunc (yetAnotherFunc arg2))

is replaced by

longFunc arg1 $ anotherFunc $ yetAnotherFunc arg2

But when I compile my program using GHCi I get a message saying:

MyFile.hs:18:18: error:
    parse error on input ‘$’
    Perhaps you intended to use TemplateHaskell
Failed, modules loaded: none.

Here's lines 16-18:

isDigit :: Char -> Bool
isDigit c =
  c `elem` $ ['0'..'9'] ++ "."

I was confused because I have used the $ operator several times (with the same compiler) like this:

main = putStrLn $ show 42

So I typed that code into my file as a test, deleted the other $ occurrences, and loaded it up.

And it worked!

Can someone please tell me what's going on?


Solution

  • You can't use ($) immediately after another infix operator. Line 18:

    c `elem` $ ['0'..'9'] ++ "."
    

    needs to be rewritten as one of the following options:

    1. Keep the parentheses as original:

      c `elem` (['0'..'9'] ++ "."])
      
    2. Apply ($) to a slice of elem:

      (c `elem`) $ ['0'..'9'] ++ "."
      
    3. Convert the call to elem to a prefix call:

      elem c $ ['0'..'9'] ++ "."
      

    I recommend option 3. Consecutive infix operators (in this case `elem` and $) do not have a well-defined priority and confuse the parser. The general rule of thumb is that an infix operator must always have a complete expression on each side. c `elem` is not a complete expression, so it is not allowed on the left of $. Similarly, $ ['0'..'9'] ++ "." is not a complete expression, so it is not allowed to be the right side of `elem`.