Home > Software design >  Haskell example how to use ifdef CPP language pragma?
Haskell example how to use ifdef CPP language pragma?

Time:11-30

I tried using ifdef in the following:

{-# LANGUAGE CPP #-}

main :: IO ()
main = do
  print "hello"
  #ifdef APP_DEBUG
    print "test"
  #endif

However the result is:

x.hs:6:3: error: Variable not in scope: (#) :: IO () -> t1 -> t0
  |
6 |   #ifdef APP_DEBUG
  |   ^

x.hs:6:4: error:
    Variable not in scope: ifdef :: t2 -> (a0 -> IO ()) -> [Char] -> t1
  |
6 |   #ifdef APP_DEBUG
  |    ^^^^^

x.hs:6:10: error: Data constructor not in scope: APP_DEBUG
  |
6 |   #ifdef APP_DEBUG
  |          ^^^^^^^^^
...

Where am I going wrong?

I can't seem to find sufficient info about this in ghc's docs here: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/utils.html?highlight=ifdef

All I found was:

#if ⟨condition⟩, #ifdef ⟨name⟩, #ifndef ⟨name⟩, #elif ⟨condition⟩, #else, #endif, #error ⟨message⟩, #warning ⟨message⟩ Conditional compilation directives are passed unmodified to the C program, C file, and C header. Putting them in the C program means that appropriate parts of the Haskell file will be skipped.

CodePudding user response:

The directives are written at the start of the line, so:

{-# LANGUAGE CPP #-}

main :: IO ()
main = do
  print "hello"
#ifdef APP_DEBUG
  print "test"
#endif

The C preprocessor runs before the Haskell compiler. It thus does not understand Haskell and will for example remove a certain code fragment (in this case if APP_DEBUG is not defined).

As @chi says, writing the hash (#) as the first line is sufficient, so:

{-# LANGUAGE CPP #-}

main :: IO ()
main = do
    print "hello"
#   ifdef APP_DEBUG
    print "test"
#   endif

is possible as well.

When compiling, the APP_DEBUG flag can be set like so:

ghc -DAPP_DEBUG x.hs
  • Related