I am the author of the operational package, which includes example code. I would like this example code to be hscolored and installed together with the API documentation, which is generated by Haddock.
I probably have to use a custom Cabal build type and create a user hook for the Haddock phase. However, I never managed to make this work. Hence, my question is:
How to include full modules as example code in Haddock?
Could you give an example of a Cabal user hook that applies hscolor to an additional source code file example.hs and joins the result with the generated Haddock documentation?
I'm a total Haskell nube and this is a shot in the dark, but couldn't you use hscolour to output the code as HTML and then do something along the lines of cabal haddock --executables --hyperlink-source to include the colorized HTML?
Related
I have a project with a a library in a few directories. The cabal file is produced with hpack and looks ok. The project builds with cabal build and the main can be run with cabal run xx.
Using repl in vscode, I get occasionally
Could not load module ‘GIS.Subdivisions’
It is a member of the hidden package ‘CatCoreConcepts-0.2’.
Perhaps you need to add ‘CatCoreConcepts’ to the build-depends in your .cabal file.
The package is, of courese, listed in the dependencies. The error is not always occuring and I assume it is a probem with some data cached in the vscode Haskell HLS plugin. Is there a simple way to clean the cache of the plugin? Restart HLS and Developer: reload window in vscode is not having any effect.
I have had the problem where VSCode thinks modules are hidden. Many answers on SO, such as this one. Possible solution, which hopefully helps,
ghc-pkg expose CatCoreConcepts
This is not an answer to the main question, but to some OP comments.
I'd say cabal documentation is good (but lengthy).
A brief summary as I understand (not official documentation)
A Package is a set of components
A component is a set of modules (haskell files)
Module-name and file-name must be equal except for entrypoints (see below)
Components can be classified in two groups:
runnables: tests, benchmarks and executables
runnables must have a unique main function called the entrypoint
In the cabal file, you can use keywords executable, test-suite and benchmark for defining runnables
Within each runnable section in the cabal file there must be a field main-is pointing to the file with the entrypoint
The file-name of the entrypoint can be whatever but the module name must be Main.
Notice that runnable components can have multiple modules (haskell files). For example you can have a test suit consisting in a file with auxiliar functions and other file with the main function. Both files conform a component (a test-suite in this case)
non-runnables: libraries
In the cabal file, you can use keywords library for defining non-runnable component
For libraries you must specify the modules which are exposed with the exposed-modules keyword.
Runnable components can import non-runnable ones even if they are defined in the same package. But viceversa is not true.
As a good practice, each component should be separated in a different folder. Some libraries expect naming convention. For example: tests to be in a folder with the same name and with test_XXXX.hs format (this is regular across programing languages, not only Haskell)
When libraries are separated in folders the field hs-source-dirs must be specified to point to the folder with the haskell files
(the name runnable is not part of the official docs, but is the way I understand)
stack works pretty much the same as cabal since the former is just a different front-end for the later. So aside from different keywords and yaml format, all of the above can be applied to stack (notice that cabal updates more often than stack, therefore some features supported by cabal can be missing in stack.)
If you find this useful, I think I am opening an issue to the cabal docs to include it.
The Haskell project I am working on generates code(and tests for it) that is intended to be used as an independent Haskell library. I want to wrap it in a cabal project, so it can be included as a dependency.
I searched for a library interface for the cabal, so I can create a cabal project at a given directory by calling some functions, but found none.
I could, of course, just run bash commands from Haskell, but it looks ugly to me.
Is there any tool that will solve my problem in a nice way?
You want the Cabal package. You can parse an existing cabal file, change stuff in the data structures, and regenerate the text representation.
Edit in answer to comment:
I don't know of any tutorials. The links I gave are for the Haddock docs, and the mapping between data types and Cabal file text is pretty straightforward. So you should probably start by writing the code to produce a PackageDescription value and then call writePackageDescription on it.
Note the existence of emptyPackageDescription, which lets you just specify the fields you want.
(Removed link to pretty printer class because PackageDescription isn't a member.)
I recently made a cabal package which can be seen here
It consists of a library and a few small example programs using it. Everything builds and works as expected.
I wanted to build an executable in a new package which uses this library, however I continue to run into a linking error I can't decipher:
/my/path/RandomAgent/.cabal-sandbox/lib/x86_64-linux-ghc-7.8.4/rlglue-0.2.1.1/libHSrlglue-0.2.1.1.a(Agent.o):(.text+0x34f1): undefined reference to `rlgluezm0zi2zi1zi1_Pathszurlglue_version1_closure'
collect2: error: ld returned 1 exit status
To make things simpler to diagnose I moved one of the examples programs into my new package and discovered even it won't build properly. You can find that version of the executable here.
From this I've concluded that the problem is likely in something I'm doing in my .cabal files, but I can't see what's wrong. The error also seems to refer to the Paths_rlglue module which cabal automatically generates for the first package.
Can anyone help me understand why I'm getting this error?
You need to include the Paths_rlglue module in exposed-modules or other-modules like any other module in your project so that Cabal will link it.
Cabal should be better about telling you what is going on, see https://github.com/haskell/cabal/issues/1746.
Looks like I missed something in the documentation for Paths_pkgname
If you decide to import the Paths_pkgname module then it must be
listed in the other-modules field just like any other module in your
package.
Adding Paths_rlglue to my library's other-modules fixed the issue. Hope this saves someone all the time I lost on this.
I have a simple web app written with scotty.
I would like to use fay to generate the front-end JS code and use shared types between the frontend and the backend.
At the moment, I run my app using cabal run: in my .cabal file I defined an "executable" and "build-depends" depends on base.
When I include "fay" and "fay-base" in "build-depends", compilation fails because Prelude is ambigous.
I understand that "fay-base" is supposed to replace the standard prelude, but I still do want to use the standard prelude in the backend code.
So, how should I write my .cabal file and what language extensions should I use in my .hs files so that std Prelude and fay Prelude can coexist? Is this the right approach?
I am using fay-0.20.1.1.
You can have fay as a dependency, it's a normal Haskell package and doesn't cause any clashes.
fay-base doesn't replace base. It's Fay's version of base and can only be used with Fay code, and vice versa.
If you want to make sure fay-base is pulled in as a dependency you can depend on another fay package (such as the small fay-text to get fay-base included as a transitive dependency)
You have some options on when to build your fay code:
At program startup using Fay's API, or fay-builder which lets you specify fay options in your Cabal file (see this blog post but skip the part about custom cabal hooks!)
On every HTTP request, useful for development. You can use the Fay API, fay-builder, yesod-fay, snaplet-fay, or happstack-fay for this.
As a Cabal hook with a custom Setup.hs (Again, bad idea)
I have 3 data constructors say A,B and C that are defined in files A.hs, B.hs, C.hs and the files are in the directory project-utils.
Now I want to use these data constructors in parts of other projects. These projects reside in totally different directories.
How do I import the data and type constructors of A, B and C in such project files?
Thanks to the first answer given below, I realized that I am looking for a skeleton to organize such project in a better way. I searched but could not find any such project skeleton.
The link provided there contains many things that are described in vague manner. For example, on line 5 there it is simple written as "..."
What i am looking for is,
The skeleton project should not be very simple "single" file project as is given on the Haskell site. But should NOT be overly complex with tons of dependencies etc that we see in many projects on hackage.
Edit: I changed the title to reflect my problem in a better way. Sorry for the inconvenience.
Make a cabal pkg out of them and install that package locally.
Follow a directory stucture as here and use those constuctors in a project rather than across projects. The stucture mentioned is basically a structure of a cabal package.
Manually add the input source while compiling through ghc or loading in ghci.
Example
ghci -i project-utils/A.hs Foo.hs
where Foo.hs uses elements exported by A.hs
May not be exactly what you're looking for, but for future readers of this question, a Haskell skeleton/template project was just released here:
https://github.com/tfausak/haskeleton
It does add some dependencies like hlint and hspec. Here is the blog post, which goes through each of the individual decisions:
http://taylor.fausak.me/2014/03/04/haskeleton-a-haskell-project-skeleton/
I found this: how to write a haskell program link as a handy reference.
#Tem Pora : you need to install yesod and yesod-bin. This link talks more about the scaffolding
cabal install yesod
cabal install yesod-bin
<cdtoprojdir> yesod init
Hope this helps.