[Haskell-cafe] The amount of CPP we have to use is getting out of hand
hesselink at gmail.com
Fri Jan 9 14:36:04 UTC 2015
I agree in principle, however, I'm not sure how feasible it is in
practice. I quickly grepped through some of our (internal and public)
packages and checked why we need CPP (I only checked MIN_VERSION_foo
data type change: 11
newly added function/type: 6
added instance: 4
function change/rename: 3
function remove: 1
deprecated function: 1
As you can see, most instances are either data type changes (these are
almost all in template haskell or haskell-src-exts) or newly added
functions where we also want to support old versions without the
function. So avoiding function changing or removing would reduce the
CPP usage in our case by about 15%, which is welcome, but doesn't
really change anything fundamental. For data type changes, I don't
really see an alternative: if new features are added the AST changes,
the AST type changes. For additions of functions, I guess we could use
a local definition even for newer versions, but that makes it less
clear when you can remove it. For instance additions, I again see no
So while I think we can do slightly better, and I would love it if
that happened, it's probably not going to be significant.
P.S. Just to add some more data, here's the packages where CPPing for:
On Fri, Jan 9, 2015 at 3:00 PM, Michael Snoyman <michael at snoyman.com> wrote:
> +1, you have my full support and agreement.
> On Fri, Jan 9, 2015, 3:57 PM Johan Tibell <johan.tibell at gmail.com> wrote:
>> (This was initially written as a Google+ post, but I'm reposting it here
>> to raise awareness of the issue.)
>> The amount of CPP we have to use in Haskell is getting a bit out of hand.
>> Here are the number of modules, per library, that use CPP for some of the
>> libraries I maintain:
>> containers 18/18
>> hashable 4/5
>> unordered-containers 6/9
>> network 3/7
>> cassava 4/16
>> cabal/cabal-install 13/75
>> cabal/Cabal 7/78
>> ekg 1/15
>> If this doesn't look like a lot to you (I hope it does!) consider than
>> some languages don't use CPP at all (e.g. Java).
>> CPP really sucks from a maintenance perspective:
>> * It's not Haskell, but this bizarre string concatenation language.
>> * The code is harder to read, bitrots more easily, and is harder to test.
>> * The code can't be compiled without using Cabal (which generates some of
>> the CPP macros for us.) This hurts e.g. ad-hoc testing/benchmarking.
>> There are a couple of reasons we use CPP, but the main one is breaking
>> changes in GHC and libraries we depend on. We need to reduce these kind of
>> breakages in the future. Dealing with breakages and maintaining the
>> resulting CPP-ed code is costing us time we could spend on other things,
>> such as improving our libraries or writing new ones. I for one would like to
>> get on with writing applications instead of spending time on run-of-the-mill
>> Often these breaking changes are done in the name of "making things
>> cleaner". Breaking changes, no matter how well-intended, doesn't make code
>> cleaner, it makes it less clean*. Users end up having to use both the old
>> "unclean" API and the new "clean" API.
>> The right way to move to evolve an new API is to add new functions and
>> data types, not modify old ones, whenever possible.
>> * It takes about 3 major GHC releases (~3 years) before you can remove the
>> CPP, but since new things keep breaking all the time you always have a
>> considerable amount of CPP.
>> -- Johan
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe