The Cabal file format works very well for small projects. However, in big projects with a library, many executables, and test suites, some irritations emerge. You need to specify dependencies in multiple places, leading to redundancy. You also have to manually add in new modules, make sure you list all modules (a real pain with executables, as problems may arise only after you build a distribution tarball), and update your module lists when you refactor.

Specifying your Cabal files in Haskell rather than in a plain-text file format helps deal with a lot of these problems. You have the full power of Haskell to make definitions in one place and then reuse them. You can also dynamically read a tree of modules and use the result, thus avoiding the need to manually update your module lists.

A disadvantage to Cartel is that it can be a bit more verbose than a vanilla Cabal file. In addition, you also have to remember to generate the new Cabal file whenever you change the script that generates your Cabal file.

Cabal already has an AST that it uses. Cartel could, perhaps, have re-used these structures. Cartel does not do this for three reasons. First, the Cabal API is a bit untidy, partially because it has to do things that Cartel doesn't have to worry about, but also because the comments in the Cabal modules themselves indicate that the whole thing could use a refactoring. Second, the Cabal developers make no commitment to keep that API stable. Third, the Cartel API tries only to replicate format of the plain-text Cabal file, which will be much more stable than the Cabal API.

Hackage:

http://hackage.haskell.org/package/cartel

Github:

https://github.com/massysett/cartel