Is There Any Haskell-Land Equivalent to the Ruby-Land's Bundler Et. Al And, If Not, How Would a Project So Structured Be Contrived

Is there any Haskell-land equivalent to the Ruby-land's Bundler et. al and, if not, how would a project so structured be contrived?

There's currently no one single way to set up a testsuite. Hopefully, people will standardize on cabal test, which is out-of-the box. In fact, both HUnit and QuickCheck are also provided with the Haskell Platform, and so setting up tests doesn't require downloading any extra dependencies.

You're correct that an old accepted answer doesn't provide information on cabal test. I edited it, and now it does! You're also probably correct that the linked page on the Haskell wiki (also written before cabal test became available) doesn't provide information on current testing best practices. It's a wiki, and I encourage folks to edit it! Note that the page does, however, provide a link to another page that describes how one might structure a more complex Haskell project.

tldr; Use cabal test. I'm fond of test-framework, which you can integrate with cabal test should you so desire. Sorry that cabal test is sort of new and not all the resources we have (generally community editable) have been updated to point to it and describe how to use it. Updating lots of resources and creating tutorials is the job of a community. We should probably do a better job promoting lots of the new awesome tools introduced to the Haskell ecosystem in the last few years.

Has anyone ever compiled a list of the imports needed to avoid the not polymorphic enough definitions in Haskell's standard libraries?

It is not as clear cut as you imagine it to be. I will list all the disadvantages I can think of off the top of my head:

First, there is no limit to how general these functions can get. For example, right now I am writing a library for indexed types that subsumes ordinary types. Every function you mentioned has a more general indexed equivalent. Do I expect everybody to switch to my library for everything? No.

Here's another example. The mapM function defines a higher order functor that satisfies the functor laws in the Kleisli category:

mapM return = return
mapM (f >=> g) = mapM f >=> mapM g

So I could argue that your traversable generalization is the wrong one and instead we should generalize it as just being an instance of a higher order functor class.

Also, check out the category-extras package for some examples of these higher order classes and functions which subsume all your examples.

There is also the issue of performance. Many of thesr more specialized functions have really finely tuned implementations that dramatically help performance. Sometimes classes expose ways to admit more performant versions, but sometimes they don't.

There is also the issue of typeclass overload. I actually prefer to minimize use of typeclasses unless they have sound laws derived from theory rather than convenience. Also, typeclasses generally play poorly with the monomorphism restriction and I enjoy writing functions without signatures for my application code.

There is also the issue of taste. A lot of people simply don't agree what is the best Haskell style. We still can't even agree on the Prelude. Speaking of which, there have been many attempts to write new Preludes, but nobody can agree on what is best so we all default back to the Haskell98 one anyway.

However, I think the overall spirit of improving things is good and the worst enemy of progress is satisfaction, but don't assume there will be a clear-cut right way to do everything.

Modern HList?

The question for any of these packages is the scope of its goals. HList is actually 5 different implementations of labels, two of type equality, two of type casting, two of Record/RecordP, and the Variant vs TIC choice. All all similar but are different trade-offs of ease of use, portability, and extensions used.

The newer GHC features (GADTs, associated types, constraint kinds, polymorphic kinds, singleton types) may allow slightly different trade offs. In particular the singleton types may allow better labels, and polymorphic kinds may allow a more elegant Typeable/Data/Generics .

The "records" package you link to depends on the "kinds" package that claims:

"Haskell has no support for subkinds and subkind polymorphism.
However, this package can be used to emulate subkinds of kind * and
subkind variables."

But this is no longer true thanks to promotion of data type to kinds in new GHC versions. So this January 2012 package may be kind-of obsolete now.

As for records, perhaps a new system will draw from the latest round of polymorphic lenses: lens and/or lens-family.

Haskell testing workflow

Getting unit testing, code coverage, and benchmarks right is mostly about picking the right tools.

  • test-framework provides a one-stop shop to run all your HUnit test-cases and QuickCheck properties all from one harness.
  • Code coverage is built into GHC in the form of the HPC tool.
  • Criterion provides some pretty great benchmarking machinery

I'll use as a running example a package that I just started enabling with unit testing, code coverage, and benchmarks:

http://github.com/ekmett/speculation

You can integrate your tests and benchmarks directly into your cabal file by adding sections for them, and masking them behind flags so that they don't make it so that every user of your library has to have access to (and want to use for themselves) the exact version of the testing tools you've chosen.

http://github.com/ekmett/speculation/blob/master/speculation.cabal

Then, you can tell cabal about how to run your test suite. As cabal test doesn't yet exist -- we have a student working on it for this year's summer of code! -- the best mechanism we have is Here is how to use cabal's user hook mechanism. This means switching to a 'Custom' build with cabal and setting up a testHook. An example of a testHook that runs a test program written with test-framework, and then applies hpc to profile it can be found here:

http://github.com/ekmett/speculation/blob/master/Setup.lhs

And then you can use test-framework to bundle up QuickCheck and HUnit tests into one program:

http://github.com/ekmett/speculation/blob/master/Test.hs

The cabal file there is careful to turn on -fhpc to enable code coverage testing, and then the testHook in Setup.lhs manually runs hpc and writes its output into your dist dir.

For benchmarking, the story is a little more manual, there is no 'cabal benchmark' option. You could wire your benchmarks into your test hook, but I like to run them by hand, since Criterion has so many graphical reporting options. You can add your benchmarks to the cabal file as shown above, give them separate compilation flags, hide them behind a cabal flag, and then use Criterion to do all the heavy lifting:

http://github.com/ekmett/speculation/blob/master/Benchmark.hs

You can then run your benchmarks from the command line and get pop-up KDE windows with benchmark results, etc.

Since in practice you're living in cabal anyways while developing Haskell code, it makes a lot of sense to integrate your toolchain with it.

Edit: Cabal test support now does exist. See http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/developing-packages.html#test-suites

testing (tasty-smallcheck) and file organisation and avoiding orphan instances

How bad convention it is to leave orphan instances in testing related code?

Not very. I agree with @Potonnier here. Orphan instances are unpleasant due to Haskell's open-world assumption, but I would argue that your testing executable target is a fairly closed world. We can reasonably expect that nobody will import the modules provided by the test executable package, and that the modules there are the "leaves" of their dependency graph. As long as that much is true, it is hard to imagine a scenario where orphan instances would lead to the worst-case scenario: something like a false positive, where the test passes due to an orphan instance when in fact it should have failed. It is not a binary decision, but I think the cost-benefit analysis here weighs against including the testing libraries as dependencies.

What special search terms do I need to look up information on writing external BBS software packages?

You probably want a "door development kit" that supports your language and BBS of choice. You'll have to consult the documentation for your specific BBS to determine what dropfiles and door routines it supports.

Applying overlay to haskellPackages

After more digging, this works for me:

self: super: {
haskellPackages = super.haskellPackages.override {
overrides = haskellSelf: haskellSuper: {
hasktags = self.haskell.lib.dontCheck haskellSuper.hasktags;
};
};
}

and place it on ~/.config/nixpkgs/overlays.nix or ~/.config/nixpkgs/overlays/ directory.

The example above is when you want to disable testing on hasktags. The idea applies for every other packages.

Testing with HTF

The new release 0.9.0.0 of HTF (see http://hackage.haskell.org/package/HTF-0.9.0.0 and https://github.com/skogsbaer/HTF/) hopefully answers all your questions. I'll summarize:

  • Answer to question 1: See the tutorial, http://hackage.haskell.org/packages/archive/HTF/0.9.0.0/doc/html/Test-Framework-Tutorial.html. It explains how to setup a main module that executes all tests defined in your package, see the section "Test definitions in multiple modules"

  • Answer to question 2: The documentation of the BlackBoxTest module http://hackage.haskell.org/packages/archive/HTF/0.9.0.0/doc/html/Test-Framework-BlackBoxTest.html now explains in detail what a black box test is and how to use it.

  • Answer to question 3: The HTF repository at https://github.com/skogsbaer/HTF/ now contains a sample directory with a complete sample project.



Related Topics



Leave a reply



Submit