CPP extension and multiline literals in Haskell
Asked Answered
M

3

12

Is it possible to use CPP extension on Haskell code which contains multiline string literals? Are there other conditional compilation techniques for Haskell?

For example, let's take this code:

-- If the next line is uncommented, the program does not compile.
-- {-# LANGUAGE CPP #-}

msg = "Hello\
  \ Wor\
  \ld!"

main = putStrLn msg

If I uncomment {-# LANGUAGE CPP #-}, then GHC refutes this code with a lexical error:

[1 of 1] Compiling Main             ( cpp-multiline.hs, cpp-multiline.o )

cpp-multiline.hs:4:17:
    lexical error in string/character literal at character 'o'

Using GHC 6.12.1, cpphs is available.

I confirm that using cpphs.compat wrapper and -pgmP cpphs.compat option helps, but I'd like to have a solution which does not depend on custom shell scripts. -pgmP cpphs does not work.

P.S. I need to use different code for GHC < 6.12 and GHC >= 6.12, is it possible without preprocessor?

UPD. In addition to the accepted answer of Ganesh, I also found that another workaround is to put all conditional declarations in a separate module with {-# LANGUAGE CPP #-} and thus avoid CPP in the modules with multiline strings.

Monochrome answered 30/3, 2010 at 22:26 Comment(2)
Why not use "Hello" ++ " Wor" ++ "ld!"?Lunatic
Because "Hello\ whitespace+ \ World!" is Haskell 98. Because there is some code around which uses it. Because " ++ " takes more space (and I dislike code beyond 80 columns). And finally, I'd like to write a patch without re-wrapping and re-formatting every multiline string in the project.Monochrome
B
6

cpphs now has a --cpp option itself, which I think makes the compat script unnecessary: see the cpphs 1.3 entry at http://haskell.org/cpphs/

I think you'd need to pass -optP --cpp to GHC (as well as -pgmP cpphs) to enable this behaviour.

Bunting answered 31/3, 2010 at 9:27 Comment(0)
E
2

It seems the GHC user manual addresses this: Section 4.10.3.1 reads

A small word of warning: -cpp is not friendly to “string gaps”.. In other words, strings such as the following:

strmod = "\
\ p \
\ "

don't work with -cpp; /usr/bin/cpp elides the backslash-newline pairs.

However, it appears that if you add a space at the end of the line, then cpp (at least GNU cpp and possibly other cpps) leaves the backslash-space pairs alone and the string gap works as expected.

Exerciser answered 31/3, 2010 at 0:53 Comment(1)
Thank you. I tried to add trailing spaces after \, but cpp just reports a warning backslash and newline separated by space, and the code still does not compile. Using GNU cpp 4.4.3.Monochrome
S
0

The decision is

strmod = "\
 p \
 "

No spaces after backslash needed plus no backslash needed at the line begin.

Sock answered 23/8 at 4:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.