Fwd: [Haskell-cafe] Data.Tree.Zipper in the standard libraries

Ups! According to the library submission procedure this message should
have been sent to libraries@haskell.org. I appologise for the multiple
copies.
---------- Forwarded message ----------
From: Krasimir Angelov
Hello, I think that the modified API (no state monad, and using Maybe) is quite nice! I implemented a version of the the suggested API using a slightly different data structure, which makes the code a bit simpler, I think. I put the code in the Haskell wiki: http://www.haskell.org/sitewiki/images/2/2d/RoseZipper.hs I also added a couple of extra functions that seemed useful, and renamed a few of the functions to be more consistent.
As for how to distribute the code, it seems that Zipper should live in the same place as Data.Tree. I think that Data.Tree is part of the "containers" package, so it would make sense to add the Zipper there as well.
-Iavor
On Sat, May 24, 2008 at 1:24 AM, Neil Mitchell
wrote: Hi,
It doesn't use State monad anymore and it returns Maybe. This seems to be the common preference, is it? Feel free to vote against. Should we change Data.Map also? There is another proposal for changes in findMin/findMax so it is better to make this two breaking changes together rather than in a later release.
The standard libraries proposal thingy is to go via the libraries list, create tickets etc. What reason is there to make this part of the base libraries, rather than a separate package on hackage? I can't see much reason to make Data.Tree part of the base libraries, other than the fact it already is, and it could easily get moved out at a future date.
We've seen there is some advantage in leaving the implementation outside the base library, as its already changed several times in the past few days.
Thnanks
Neil _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Sat, May 31, 2008 at 10:44:40AM +0200, Krasimir Angelov wrote:
I was silent for some time but in this time I created QuickCheck tests for Data.Tree.Zipper which achieve 100% coverage with HPC. I also created a ticket for it: Ticket #2324
http://hackage.haskell.org/trac/ghc/ticket/2324
The attached file is the current implementation and it contains the version updated from Iavor Diatchki. It has the advantage that it also works with forests, not just with trees.
Initially I thought that complete testsuite for such a simple module might be overkill but actually I found a bug :-) in the splitChildren function which is now fixed.
So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right? As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time. I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot. Adding a unit test for the bug you found is certainly a good idea, though! [1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html Thanks Ian

In this case the recommendation to write QuickCheck tests should be
removed from the library submission procedure. I don't want to do
wasted work again!
On Sat, May 31, 2008 at 1:16 PM, Ian Lynagh
So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian

It's not wasted work. As far as I know, only Ian advocates against including tests. Having worked on several data structure libraries, I've found that QuickCheck regularly catches errors that appear, and ensure over the long term that code remains stable. -- Don kr.angelov:
In this case the recommendation to write QuickCheck tests should be removed from the library submission procedure. I don't want to do wasted work again!
On Sat, May 31, 2008 at 1:16 PM, Ian Lynagh
wrote: So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hi Krasimir,
What is the strong justification for adding this to the base library?
Is there some particular reason that it can't be done outside of base,
or is there some particular need that makes this code desirable in the
base libraries? Could it be added as a separate library on hackage,
worked on for a while, and then merged into the base latter if
appropriate?
I worry that in the last couple of weeks since you first brought this
code up it seems like its been reimplemented from scratch with a
different interface. Once it goes in the base library, those decisions
are fixed in stone. If it gets some real world use in a library first,
then its much clearer if there are any flaws or extensions required.
Thanks
Neil
On Sat, May 31, 2008 at 6:12 PM, Don Stewart
It's not wasted work. As far as I know, only Ian advocates against including tests.
Having worked on several data structure libraries, I've found that QuickCheck regularly catches errors that appear, and ensure over the long term that code remains stable.
-- Don
kr.angelov:
In this case the recommendation to write QuickCheck tests should be removed from the library submission procedure. I don't want to do wasted work again!
On Sat, May 31, 2008 at 1:16 PM, Ian Lynagh
wrote: So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Neil Mitchell wrote:
Hi Krasimir,
What is the strong justification for adding this to the base library? Is there some particular reason that it can't be done outside of base, or is there some particular need that makes this code desirable in the base libraries? Could it be added as a separate library on hackage, worked on for a while, and then merged into the base latter if appropriate?
'containers', not 'base'. But still, I think it should stay in a separate package. Someday Data.Tree may be removed from the more-used containers too. (do we know who does use Data.Tree, btw?) -Isaac

and also Gtk2Hs, Yi, GF, XML Toolbox and probably some other.
On 6/1/08, Ross Paterson
On Sun, Jun 01, 2008 at 12:49:39PM -0400, Isaac Dupree wrote:
'containers', not 'base'. But still, I think it should stay in a separate package. Someday Data.Tree may be removed from the more-used containers too. (do we know who does use Data.Tree, btw?)
Data.Graph for one. _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Sun, 2008-06-01 at 12:49 -0400, Isaac Dupree wrote:
Neil Mitchell wrote:
Hi Krasimir,
What is the strong justification for adding this to the base library? Is there some particular reason that it can't be done outside of base, or is there some particular need that makes this code desirable in the base libraries? Could it be added as a separate library on hackage, worked on for a while, and then merged into the base latter if appropriate?
'containers', not 'base'. But still, I think it should stay in a separate package. Someday Data.Tree may be removed from the more-used containers too. (do we know who does use Data.Tree, btw?)
It's used ad-hoc in lots of programs whenever people want a rose-tree. It's convenient to have and as Ross says it's used in the public interface of Data.Graph. If anything I think it should be extended. For example where is the post-order flattening, the all-paths etc. There are useful operations defined for it in Data.Graph that should be moved to Data.Tree itself. Duncan

I don't propose to add it to base but to containers where the
Data.Tree module already is. This sounds like a logical place for me.
The implementation has been changed but I can't say that it was
rewritten from scratch. Part of my idea was to share what I use and to
hear some ideas for improvements. That is exactly what happened and I
am quite satisfied. Even if it has to be changed later I don't see any
problem with this. Changes are made to the Map and Set modules as
well. The process package seems to have quite different API now. Even
if the zipper is in different package then this doesn't mean that we
don't have to care about the backward compatibility.
On 6/1/08, Neil Mitchell
Hi Krasimir,
What is the strong justification for adding this to the base library? Is there some particular reason that it can't be done outside of base, or is there some particular need that makes this code desirable in the base libraries? Could it be added as a separate library on hackage, worked on for a while, and then merged into the base latter if appropriate?
I worry that in the last couple of weeks since you first brought this code up it seems like its been reimplemented from scratch with a different interface. Once it goes in the base library, those decisions are fixed in stone. If it gets some real world use in a library first, then its much clearer if there are any flaws or extensions required.
Thanks
Neil
On Sat, May 31, 2008 at 6:12 PM, Don Stewart
wrote: It's not wasted work. As far as I know, only Ian advocates against including tests.
Having worked on several data structure libraries, I've found that QuickCheck regularly catches errors that appear, and ensure over the long term that code remains stable.
-- Don
kr.angelov:
In this case the recommendation to write QuickCheck tests should be removed from the library submission procedure. I don't want to do wasted work again!
On Sat, May 31, 2008 at 1:16 PM, Ian Lynagh
wrote: So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

hmm, that's the most convincing argument I've seen so far, so I'll try to see what still doesn't seem right to me: - if you'd release a separate package then would it have a 0.x version number now, or 1.0 -- does it have a degree of initial stableness? (should anything be assumed to have that the first time it's put on Hackage, if it's new?) - Luckily we don't have to worry much about release cycles -- we just make a new release of even ghc-boot-libs whenever we want to change anything in it, more-or-less (I think?) - Dependencies in cabal files are a bigger problem. They make it painful to split packages later... especially if you split them soon after adding something to them (e.g. bytestring, though that was worse because it involved base as well as GHC internals). But if you can be sure you're not going to want to remove it, it's only slightly painful in terms of allowed dependencies (e.g. can't use with an earlier version of containers, and clients have to specify dependency by containers version-number) Krasimir Angelov wrote:
I don't propose to add it to base but to containers where the Data.Tree module already is. This sounds like a logical place for me. The implementation has been changed but I can't say that it was rewritten from scratch. Part of my idea was to share what I use and to hear some ideas for improvements. That is exactly what happened and I am quite satisfied. Even if it has to be changed later I don't see any problem with this. Changes are made to the Map and Set modules as well. The process package seems to have quite different API now. Even if the zipper is in different package then this doesn't mean that we don't have to care about the backward compatibility.
On 6/1/08, Neil Mitchell
wrote: Hi Krasimir,
What is the strong justification for adding this to the base library? Is there some particular reason that it can't be done outside of base, or is there some particular need that makes this code desirable in the base libraries? Could it be added as a separate library on hackage, worked on for a while, and then merged into the base latter if appropriate?
I worry that in the last couple of weeks since you first brought this code up it seems like its been reimplemented from scratch with a different interface. Once it goes in the base library, those decisions are fixed in stone. If it gets some real world use in a library first, then its much clearer if there are any flaws or extensions required.
Thanks
Neil
On Sat, May 31, 2008 at 6:12 PM, Don Stewart
wrote: It's not wasted work. As far as I know, only Ian advocates against including tests.
Having worked on several data structure libraries, I've found that QuickCheck regularly catches errors that appear, and ensure over the long term that code remains stable.
-- Don
kr.angelov:
In this case the recommendation to write QuickCheck tests should be removed from the library submission procedure. I don't want to do wasted work again!
On Sat, May 31, 2008 at 1:16 PM, Ian Lynagh
wrote: So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hi
well. The process package seems to have quite different API now. Even if the zipper is in different package then this doesn't mean that we don't have to care about the backward compatibility.
If the package lives on its own, the author is responsible for it. If you decide you made a mistake in the interface you can change it (I did this for TagSoup). If you want to provide a backwards compatible version you provide Data.Zipper.OldVersion (I did this for FilePath). If you want to move the module you can do so (I did this for Safe). If you want to add new features you can do so without asking anyone (I did this for Yhc.Core). If you want to optimise the code you can do so without asking anyone (I did this for Homeomorphic). There are many benefits to having a package outside the base library. In 3 of the above cases being inside the base library would have mean I just couldn't do what I wanted. In the last 2 cases I would have had to submit library proposals. I think that new big features live best in a separate package, at least until a couple of people have played with them and incrementally improved them. As Hackage improves, the benefits of being in the base library decrease substantially. Thanks Neil

Hello,
Neil, nobody is suggesting to add the zipper to the "base" package, we
are talking about the "containers" package, which is also available
from hackage (http://hackage.haskell.org/cgi-bin/hackage-scripts/package/containers)
. The whole point of splitting the large "base" library was so that
we can update the different components separately.
In general, I agree with Neil's sentiment that we don't want to lump
together things that are conceptually different because the extra
dependencies make it harder to update packages. However, we should
also watch out for the other extreme---where each module ends up in a
separate package. While this leads to the most flexibility, it also
introduces extra overhead in managing the dependencies, and finding
the libraries that we need.
In this case, the zipper is the iterator type for trees, so I think
that it is justified to add it to the same package as trees.
As for the discussion about tests: I don't see how writing down the
properties of the program (e.g., in the form of QC properties) can be
a bad thing, so I really think that it is great the Krasimir took the
time to provide a set of tests for the zipper implementation. We need
more of this sort of thing, not less! The fact that the GHC test
suite is taking too long to run, should not dictate how programmers
test their libraries. If there is a pragmatic problem, I think that
Duncan's suggests provide a good solution---simply run the tests more
selectively.
-Iavor
On Mon, Jun 2, 2008 at 4:11 AM, Neil Mitchell
Hi
well. The process package seems to have quite different API now. Even if the zipper is in different package then this doesn't mean that we don't have to care about the backward compatibility.
If the package lives on its own, the author is responsible for it. If you decide you made a mistake in the interface you can change it (I did this for TagSoup). If you want to provide a backwards compatible version you provide Data.Zipper.OldVersion (I did this for FilePath). If you want to move the module you can do so (I did this for Safe). If you want to add new features you can do so without asking anyone (I did this for Yhc.Core). If you want to optimise the code you can do so without asking anyone (I did this for Homeomorphic).
There are many benefits to having a package outside the base library. In 3 of the above cases being inside the base library would have mean I just couldn't do what I wanted. In the last 2 cases I would have had to submit library proposals. I think that new big features live best in a separate package, at least until a couple of people have played with them and incrementally improved them. As Hackage improves, the benefits of being in the base library decrease substantially.
Thanks
Neil _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hi
Neil, nobody is suggesting to add the zipper to the "base" package, we are talking about the "containers" package, which is also available
I was referring to base as "the set of Core libraries" - my terminology was wrong, but my arguments were written with me thinking "containers", so still apply.
In this case, the zipper is the iterator type for trees, so I think that it is justified to add it to the same package as trees.
Talking to people on IRC today it appears there is a reasonably large design space for a zipper interface. If this is true, then putting a zipper in the containers package without some significant real-world experience is probably premature. Thanks Neil

On 6/3/08, Neil Mitchell
Talking to people on IRC today it appears there is a reasonably large design space for a zipper interface. If this is true, then putting a zipper in the containers package without some significant real-world experience is probably premature.
Well if this is the common agreement then I will withdraw my proposal. Maintaining a single module package floating around is too much effort for me. I prefer to keep a local copy in the projects that need it instead of maintaining an extra dependencies and to force the users to download extra software. I am sorry for the wasted time and effort. Krasimir

On Tue, Jun 3, 2008 at 12:05 AM, Neil Mitchell
Talking to people on IRC today it appears there is a reasonably large design space for a zipper interface. If this is true, then putting a zipper in the containers package without some significant real-world experience is probably premature.
On the other hand, having something available in the containers package for everyone to experiment with seems a good way to evolve towards a better design. I'd still vote for adding the module, and flag it with "experimental" stability if there are worries of instability. Cheers, JP.

Hi
On the other hand, having something available in the containers package for everyone to experiment with seems a good way to evolve towards a better design.
I'd still vote for adding the module, and flag it with "experimental" stability if there are worries of instability.
If you want to mark it as experimental, it should not be in the core libraries. Evolving designs are great, but libraries@ should not be the maintainer of such a module. I'm not sure if that is a general policy, but I would be surprised to hear if it was a minority opinion.
Well if this is the common agreement then I will withdraw my proposal. Maintaining a single module package floating around is too much effort for me. I prefer to keep a local copy in the projects that need it instead of maintaining an extra dependencies and to force the users to download extra software. I am sorry for the wasted time and effort.
I think that's a real shame. Maintaining a cabal package is relatively little effort. I have several packages which are just one module long (see for example Safe - which is not only one module, but every definition within it is only one line!). With cabal-install, the extra effort to install dependencies is literally nothing - its all handled automatically. And once you've got some users, and some varied experience of using the library, then I think making a library proposal would be a good idea. Thanks Neil

Hi,
I was referring to base as "the set of Core libraries" - my terminology was wrong, but my arguments were written with me thinking "containers", so still apply.
You arguments suggest that every module should be in a separate package. In my experience this is a bad idea.
Talking to people on IRC today it appears there is a reasonably large design space for a zipper interface. If this is true, then putting a zipper in the containers package without some significant real-world experience is probably premature.
Could you elaborate on this? What are the different design choices that your IRC discussions revealed? The zipper for trees is a fairly standard structure so I would be very surprised if the interface becomes drastically different. I would grant you that we may want to add some more functions to the library at some point, but apart from that the basics really should be much like what Krasimir posted.
I think that's a real shame. Maintaining a cabal package is relatively little effort. I have several packages which are just one module long (see for example Safe - which is not only one module, but every definition within it is only one line!). With cabal-install, the extra effort to install dependencies is literally nothing - its all handled automatically. And once you've got some users, and some varied experience of using the library, then I think making a library proposal would be a good idea.
Mico-managing a slew of different packages is a pain, especially if you are actually serious about maintaining the packages. It also makes finding packages and keeping track of the dependencies between them hard---cabal-install only helps with downloading the right packages, and it is not always an option to use it. But enough general discussions :-) Do people find any concrete problems with the zipper implementation? -Iavor

Hi
I was referring to base as "the set of Core libraries" - my terminology was wrong, but my arguments were written with me thinking "containers", so still apply.
You arguments suggest that every module should be in a separate package. In my experience this is a bad idea.
I think that any brand new module being proposed for the Core libraries should first be available as a package, and then integrated into the Core libraries afterwards. I think the barrier for getting things in the Core libraries should be much higher. For non-Core libraries, I would advocate grouping modules by functionality into packages - but for non-Core libraries people are free to do whatever they want :-)
Talking to people on IRC today it appears there is a reasonably large design space for a zipper interface. If this is true, then putting a
Could you elaborate on this? What are the different design choices that your IRC discussions revealed?
ndm> I was wondering if there is just one way to do a zipper? _other person_> I've done them using several different interfaces, I'm not quite sure which one I like best yet. (I know who _other person_ is, but it seems unfair to quote IRC with names back at people, given the instant and non-committal nature of IRC)
I think that's a real shame. Maintaining a cabal package is relatively little effort. I have several packages which are just one module long
Mico-managing a slew of different packages is a pain, especially if you are actually serious about maintaining the packages. It also makes finding packages and keeping track of the dependencies between them hard---cabal-install only helps with downloading the right packages, and it is not always an option to use it.
If you have a package for every single module, then yes. If not, then its not that bad. Yes, you need some more infrastructure, but Cabal provides most of it. Maintaining a zipper package for a few months really wouldn't be that much work. Thanks Neil

On Tue, Jun 3, 2008 at 11:23 PM, Neil Mitchell
ndm> I was wondering if there is just one way to do a zipper? _other person_> I've done them using several different interfaces, I'm not quite sure which one I like best yet.
(I know who _other person_ is, but it seems unfair to quote IRC with names back at people, given the instant and non-committal nature of IRC)
I would prefer the important discussions to be led not in IRC but in the mailing list. I personally very rarely (almost never) go to channel #haskell because I can't concentrate on my work if I have to follow the endless discussions in the channel. By the way so far your voice seems to be the only one against. I would like to hear what the other guys think. Krasimir

On Wed, 2008-06-04 at 08:29 +0200, Krasimir Angelov wrote:
On Tue, Jun 3, 2008 at 11:23 PM, Neil Mitchell
wrote: ndm> I was wondering if there is just one way to do a zipper? _other person_> I've done them using several different interfaces, I'm not quite sure which one I like best yet.
(I know who _other person_ is, but it seems unfair to quote IRC with names back at people, given the instant and non-committal nature of IRC)
I would prefer the important discussions to be led not in IRC but in the mailing list. I personally very rarely (almost never) go to channel #haskell because I can't concentrate on my work if I have to follow the endless discussions in the channel. By the way so far your voice seems to be the only one against. I would like to hear what the other guys think.
I would tend to agree with Neil that significant additions to the core libraries should be proven first as separate packages and integrated later. Duncan

Hi,
If this is the consensus, than people that feel this way should write
a document describing the new process so that we know how to
contribute code. Based on the current sentiments, we should decide at
least on the following:
- what is a "core" package
Perhaps, a package that is distributed with GHC? But then, we should
be having this discussion on the GHC users list... Also, was not the
whole point of splitting the base library, so that we can gain the
freedom to update libraries independent of implementations?
- what constitutes a "significant" change
Not sure how to define this. I would be weary of changes to the
existing functions/types in the APIs of existing modules. But adding
extra functionality? Especially, if---like in the case of
Zipper---the implementation can be more or less computed from an
existing definition in the package (I am referring to the fact that
the zipper is the derivative of Tree, for details you can look at
Conor's paper).
- what makes code "proven"
Again, not sure how to define this. The code for Zipper has QC
tests that cover it 100%, according to HPC. Of course, this does not
mean that it is perfect, but certainly should give us some assurance
that it works. Does code have to sit on hackage for a certain amount
of time, before it can be added to the libraries? Or are we going to
require that it is already used by many people as a separate package,
and then we are going to ask everyone to change their code, so that
they can start using it from the new location? Neither option seems
very nice.
But more to the point though, does anyone have any suggestions about
what may be wrong with the Zipper concretely, rather then the library
process in general? Neil, the sniplet that you posted from the IRC
channel does not give us an idea of what we might want to change.
-Iavor
On Wed, Jun 4, 2008 at 2:39 AM, Malcolm Wallace
Duncan Coutts
wrote: I would tend to agree with Neil that significant additions to the core libraries should be proven first as separate packages and integrated later.
+1
Regards, Malcolm _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Iavor Diatchki wrote:
Hi, If this is the consensus, than people that feel this way should write a document describing the new process so that we know how to contribute code.
+1. unfortunately, I'm not volunteering today
- what is a "core" package Perhaps, a package that is distributed with GHC?
Evidently not -- mtl is probably considered a core package, and, it's not distributed with GHC. Perhaps, a package that is maintained by libraries@haskell.org?
- what constitutes a "significant" change Not sure how to define this. I would be weary of changes to the existing functions/types in the APIs of existing modules. But adding extra functionality? Especially, if---like in the case of Zipper---the implementation can be more or less computed from an existing definition in the package (I am referring to the fact that the zipper is the derivative of Tree, for details you can look at Conor's paper).
- what makes code "proven" Again, not sure how to define this. The code for Zipper has QC tests that cover it 100%, according to HPC.
Proven to be a useful interface, more than proven to be bug-free[*], IMHO. It's easier for us to maintain a package by perfecting its documentation, implementation etc. as a community; but harder to explore large design spaces when an existing solution comes to be felt as inadequate for the purposes it's used for. [*] of course you can't *prove* anything to be bug-free, let's say "demonstrated not to have too many fatal bugs" :-) -Isaac

On Wed, Jun 04, 2008 at 10:14:59AM -0700, Iavor Diatchki wrote:
extra functionality? Especially, if---like in the case of Zipper---the implementation can be more or less computed from an existing definition in the package (I am referring to the fact that the zipper is the derivative of Tree, for details you can look at Conor's paper).
I've just skimmed http://citeseer.ist.psu.edu/472190.html The Derivative of a Regular Type is its Type of One-Hole Contexts (Extended Abstract) (2001) Conor McBride Given the way people had been appealing to it, I has assumed that datastructure derivatives were some general thing, but it looks like they are actually just a way of describing a particular concrete implementation of zippers. I'm not even sure how well the theoretical connection applies to the variable branching degree of Data.Tree. Also, it's actually the derivative of Forest, not Tree, right? Which is why toTree can lose information, here the b and c trees: Data.Tree.Zipper> toTree (Loc (Node 'a' []) [Node 'b' []] [Node 'c' []] []) Node {rootLabel = 'a', subForest = []} This feels a little scary to me. Also, I think that technically it doesn't follow the paper, in that it stores the parents in the reverse order. That aside, the fact the datastructure is a derivative doesn't tell us that it is efficient (in fact, it is more efficient because it /isn't/ a straightforward derivative, but reverses the parent order as above), that we have implemented the "right" methods to operate on it, that we have chosen the "best" names for those methods, etc.
- what makes code "proven" Again, not sure how to define this. The code for Zipper has QC tests that cover it 100%, according to HPC.
The question is more "is it the best interface" than "is the code correct".
Or are we going to require that it is already used by many people as a separate package, and then we are going to ask everyone to change their code, so that they can start using it from the new location?
The only change that should be needed is changing the Cabal dependencies (and even that isn't strictly necessary, as you can make an empty zipper package that depends on containers (>= n).
But more to the point though, does anyone have any suggestions about what may be wrong with the Zipper concretely, rather then the library process in general? Neil, the sniplet that you posted from the IRC channel does not give us an idea of what we might want to change.
Agreed: It sounds like people who have thought about this in the past have found some design choices; it might be useful if they could explain what they are.
I would tend to agree with Neil that significant additions to the core libraries should be proven first as separate packages and integrated later.
+1
I agree too - no matter how much you mark it experimental, people will still complain loudly if you try to change the interface of a module in the "standard" libraries. Thanks Ian

igloo:
On Wed, Jun 04, 2008 at 10:14:59AM -0700, Iavor Diatchki wrote:
extra functionality? Especially, if---like in the case of Zipper---the implementation can be more or less computed from an existing definition in the package (I am referring to the fact that the zipper is the derivative of Tree, for details you can look at Conor's paper).
I've just skimmed http://citeseer.ist.psu.edu/472190.html The Derivative of a Regular Type is its Type of One-Hole Contexts (Extended Abstract) (2001) Conor McBride
Given the way people had been appealing to it, I has assumed that datastructure derivatives were some general thing, but it looks like they are actually just a way of describing a particular concrete implementation of zippers. I'm not even sure how well the theoretical connection applies to the variable branching degree of Data.Tree.
Also, it's actually the derivative of Forest, not Tree, right? Which is why toTree can lose information, here the b and c trees: Data.Tree.Zipper> toTree (Loc (Node 'a' []) [Node 'b' []] [Node 'c' []] []) Node {rootLabel = 'a', subForest = []} This feels a little scary to me.
Also, I think that technically it doesn't follow the paper, in that it stores the parents in the reverse order.
That aside, the fact the datastructure is a derivative doesn't tell us that it is efficient (in fact, it is more efficient because it /isn't/ a straightforward derivative, but reverses the parent order as above), that we have implemented the "right" methods to operate on it, that we have chosen the "best" names for those methods, etc.
Quite so, the list derivative xmonad uses, for example, taken straight from the Huet paper, data Stack a = Stack { focus :: !a -- focused thing in this set , up :: [a] -- clowns to the left , down :: [a] } -- jokers to the right deriving (Show, Read, Eq) has an integration function, integrate :: Stack a -> [a] integrate (Stack x l r) = reverse l ++ x : r and, e.g. moving around the structure, focusUp (Stack t (l:ls) rs) = Stack l ls (t:rs) focusUp (Stack t [] rs) = Stack x xs [] where (x:xs) = reverse (t:rs) The structure of the type is derived, the implementation of the API is able to make further decisions appropriate to the representation. -- Don

Ian Lynagh wrote:
I've just skimmed http://citeseer.ist.psu.edu/472190.html The Derivative of a Regular Type is its Type of One-Hole Contexts (Extended Abstract) (2001) Conor McBride
Given the way people had been appealing to it, I has assumed that datastructure derivatives were some general thing, but it looks like they are actually just a way of describing a particular concrete implementation of zippers. I'm not even sure how well the theoretical connection applies to the variable branching degree of Data.Tree.
This is quite right, the connection between zippers and derivatives is not as straightforward as it seems. First, they are different things. You can obtain a zipper for an inductive data structure type Foo = µ x. F x by differentiating the functor F , but you can't differentiate Foo itself. (I think that the zipper may even depend on the particular choice of F.) Yet, both may coincide; the derivative of type List a = µ x . 1 + (a, x) with respect to a and the zipper for lists are pretty much the same.
Also, I think that technically it doesn't follow the paper, in that it stores the parents in the reverse order.
That aside, the fact the datastructure is a derivative doesn't tell us that it is efficient (in fact, it is more efficient because it /isn't/ a straightforward derivative, but reverses the parent order as above), that we have implemented the "right" methods to operate on it, that we have chosen the "best" names for those methods, etc.
Correct, applying the rules of differentiation directly usually does not give the most efficient structure. When differentiating fixed points, one usually ends up with something like type DF a = µ x . T a + (S a, x) which is basically a list of S a that doesn't end with [] but with a value of type T a . Of course, this is isomorphic to type DF' a = ([S a], T a) with the list reversed; but this isomorphism is an optimization.
Also, it's actually the derivative of Forest, not Tree, right? Which is why toTree can lose information, here the b and c trees: Data.Tree.Zipper> toTree (Loc (Node 'a' []) [Node 'b' []] [Node 'c' []] []) Node {rootLabel = 'a', subForest = []} This feels a little scary to me.
Yes. A zipper for a tree would have to carry the value a around. Regards, apfelmus PS: The article in the wikibook http://en.wikibooks.org/wiki/Haskell/Zippers tries to point out the above distinctions.

On Wed, Jun 04, 2008 at 11:11:58PM +0200, apfelmus wrote:
Ian Lynagh wrote:
Also, it's actually the derivative of Forest, not Tree, right? Which is why toTree can lose information, here the b and c trees: Data.Tree.Zipper> toTree (Loc (Node 'a' []) [Node 'b' []] [Node 'c' []] []) Node {rootLabel = 'a', subForest = []} This feels a little scary to me.
I should expand on that: I wonder if toTree should return Maybe (Tree a) which returns Nothing if either sibling is non-empty.
Yes. A zipper for a tree would have to carry the value a around.
It would actually simplify the datastructure; rather than data TreeLoc a = Loc { tree :: Tree a -- ^ The currently selected tree. , lefts :: Forest a -- ^ Siblings on the left, closest first. , rights :: Forest a -- ^ Siblings on the right, closest first. , parents :: [(Forest a, a, Forest a)] -- ^ The contexts of the parents for this location. } deriving (Read,Show,Eq) we could have just data TreeLoc a = Loc { tree :: Tree a -- ^ The currently selected tree. , parents :: [(Forest a, a, Forest a)] -- ^ The contexts of the parents for this location. } deriving (Read,Show,Eq) where the Forests are now children of the parent nodes, rather than their siblings. The cost is that you now can't represent forests nicely. Thanks Ian

Hi Ian,
Thanks for discussing the actual Zipper!
On Wed, Jun 4, 2008 at 2:36 PM, Ian Lynagh
On Wed, Jun 04, 2008 at 11:11:58PM +0200, apfelmus wrote:
Data.Tree.Zipper> toTree (Loc (Node 'a' []) [Node 'b' []] [Node 'c' []] []) Node {rootLabel = 'a', subForest = []} This feels a little scary to me.
I should expand on that: I wonder if toTree should return Maybe (Tree a) which returns Nothing if either sibling is non-empty.
The idea is that "toTree" computes the tree that contains the current location. It makes no calims about this being the only tree in the forest. I think it is useful to have such a function. The function "toForest" computes the entire forest. You can always get the "Maybe" version by examining the result of "toForest", but if you think that it would be useful, we could also add another function to do it (perhaps it belongs to Tree: forestToTree?)
It would actually simplify the datastructure; rather than ... we could have just
data TreeLoc a = Loc { tree :: Tree a -- ^ The currently selected tree. , parents :: [(Forest a, a, Forest a)] -- ^ The contexts of the parents for this location. } deriving (Read,Show,Eq)
where the Forests are now children of the parent nodes, rather than their siblings. The cost is that you now can't represent forests nicely.
Yeah, this is nice. I think that it would be good to support working with forests though. While we are on questions of API, currently the insertion functions of the Zipper make the inserted tree be the current tree. It is also easy to have functions that insert to the left or to the right but don't change the current tree. What do you think? -Iavor

Hi,
Well, it is clear that the Haskell community (as represented by the
few vocal participants in this discussion) is not interested in having
a zipper module in the containers package at this point in time. I am
not sure of the technical reasons for that, but my understanding is
that the general concern is that a lack of experience of working with
zippers has caused some uncertainty about the API of the library. To
solve this problem it was suggested that the zipper "library" should
be distributed as a separate package.
In the previous emails I explained why I think that this is a bad
idea, but it would appear that I am in the minority. To avoid having
the code get lost, I have created a repository, so that interested
parties can continue using/improving the code (yes, it is also a cabal
package :-). The repository is available here:
git://github.com/yav/haskell-zipper.git
-Iavor
PS: By the way, I was really impressed with github---it is very easy
to start new projects and it offers a number of very nice features.
On Sun, Jun 8, 2008 at 1:54 PM, Ian Lynagh
On Sat, Jun 07, 2008 at 11:05:56AM -0700, Iavor Diatchki wrote:
What do you think?
I think that before semi-freezing the API, it would be good to get some more experience with the library so that these questions are easier to answer.
Thanks Ian

On Wed, Jun 4, 2008 at 10:21 PM, Ian Lynagh
On Wed, Jun 04, 2008 at 10:14:59AM -0700, Iavor Diatchki wrote:
- what makes code "proven" Again, not sure how to define this. The code for Zipper has QC tests that cover it 100%, according to HPC.
The question is more "is it the best interface" than "is the code correct".
We really need something like the Python community's Python Enhancement Proposals (PEPs) [1] where different design trade-offs, corner cases, performance, etc. can be discussed before something is accepted into core libraries. It think that process has work very well and is probably one of the reasons why Python have such nice (and consistent!) standard libraries. 1. http://www.python.org/dev/peps/ -- Johan

johan.tibell:
On Wed, Jun 4, 2008 at 10:21 PM, Ian Lynagh
wrote: On Wed, Jun 04, 2008 at 10:14:59AM -0700, Iavor Diatchki wrote:
- what makes code "proven" Again, not sure how to define this. The code for Zipper has QC tests that cover it 100%, according to HPC.
The question is more "is it the best interface" than "is the code correct".
We really need something like the Python community's Python Enhancement Proposals (PEPs) [1] where different design trade-offs, corner cases, performance, etc. can be discussed before something is accepted into core libraries. It think that process has work very well and is probably one of the reasons why Python have such nice (and consistent!) standard libraries.
I'd be happy to have anything that helps the process run smoothly. The current approach of mail conversations makes it difficult to determine the result, if there are any objections, I've noticed. -- Don

Iavor Diatchki wrote:
Or are we going to require that it is already used by many people as a separate package, and then we are going to ask everyone to change their code, so that they can start using it from the new location?
As an aside, I don't see why this would require anyone to change their code. So long as people choose good module names, the movement of some module from one package to another at most changes a Makefile or .cabal file. I actually rather like this about Haskell as it currently exists; third-party packages don't have to be isolated behemoths walled off by namespace issues. In fact, there are good examples of cases where external packages define modules in Data.* module hierarchy with perfectly logical names. The code is then entirely independent of packaging concerns. -- Chris

Hello,
When I said "code" I was referring to the build system as well as the
Haskell code. "Just changing a Makefile" is not a trivial issue, and
even if it was, it would still be a change that somebody would have to
make in all packages that depend on the code (and possibly, in a bunch
of packages that depend on _these_ packages to chanage version numbers
in dependecies).
And how would you setup the dependencies in the new code? You would
either have to use an extra flag, just for the one Zipper module, or
you would need to have some kind of disjunction of dependencies.
Something like:
(containers >= X) or (containers > Y and containers < X and Zipper)
where X is the new code got moved to containers, and Y is a known good
version of containers. Does Cabal even support this kind of thing?
Of course, things like that are unavoidable in general, the question
is how often do we want to ask programmers to deal with this kind of
thing. I think that it is completely unwarranted in the case of the
single ZIpper module.
-Iavor
On Fri, Jun 6, 2008 at 5:52 PM, Chris Smith
Iavor Diatchki wrote:
Or are we going to require that it is already used by many people as a separate package, and then we are going to ask everyone to change their code, so that they can start using it from the new location?
As an aside, I don't see why this would require anyone to change their code. So long as people choose good module names, the movement of some module from one package to another at most changes a Makefile or .cabal file. I actually rather like this about Haskell as it currently exists; third-party packages don't have to be isolated behemoths walled off by namespace issues. In fact, there are good examples of cases where external packages define modules in Data.* module hierarchy with perfectly logical names. The code is then entirely independent of packaging concerns.
-- Chris
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

duncan.coutts:
On Wed, 2008-06-04 at 08:29 +0200, Krasimir Angelov wrote:
On Tue, Jun 3, 2008 at 11:23 PM, Neil Mitchell
wrote: ndm> I was wondering if there is just one way to do a zipper? _other person_> I've done them using several different interfaces, I'm not quite sure which one I like best yet.
(I know who _other person_ is, but it seems unfair to quote IRC with names back at people, given the instant and non-committal nature of IRC)
I would prefer the important discussions to be led not in IRC but in the mailing list. I personally very rarely (almost never) go to channel #haskell because I can't concentrate on my work if I have to follow the endless discussions in the channel. By the way so far your voice seems to be the only one against. I would like to hear what the other guys think.
I would tend to agree with Neil that significant additions to the core libraries should be proven first as separate packages and integrated later.
I wonder if there's a good case already: The zipper module here has: * A solid theoretical foundation (its a straightforward derivative of a data type) * Sensible API derived from Huet's papers, then implemented and used for Yi, one of the larger Haskell projects * Rich testsuite -- with 100% test coverage And its a derivative of a type in containers, so makes sense to be in containers, no? If not, maybe we need to clarify the process for inclusion in the core lib set. E.g. the above constraints, and "6 months testing as a standalone package" -- Don

Don Stewart wrote:
I wonder if there's a good case already:
The zipper module here has:
* A solid theoretical foundation (its a straightforward derivative of a data type)
and seems to go along with that data type, in the places it's used? is that right?
* Sensible API derived from Huet's papers, then implemented and used for Yi, one of the larger Haskell projects
interesting, so Yi would start using the version in `containers` if we put it there? And so would Krasimir's projects? If so, that sounds like a solid user-base... hmm. -Isaac

Hello Isaac, Wednesday, June 4, 2008, 10:29:50 PM, you wrote:
so Yi would start using the version in `containers` if we put it there? And so would Krasimir's projects? If so, that sounds like a solid user-base...
i wonder how they will use it if containers package is bundled with ghc and used by almost every other library? does this mean that process of Yi installation, for example, will require to recompile every library installed that use containers? -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Tue, Jun 3, 2008 at 10:58 AM, Neil Mitchell
Hi
Well if this is the common agreement then I will withdraw my proposal. Maintaining a single module package floating around is too much effort for me. I prefer to keep a local copy in the projects that need it instead of maintaining an extra dependencies and to force the users to download extra software. I am sorry for the wasted time and effort.
I think that's a real shame. Maintaining a cabal package is relatively little effort. I have several packages which are just one module long (see for example Safe - which is not only one module, but every definition within it is only one line!). With cabal-install, the extra effort to install dependencies is literally nothing - its all handled automatically. And once you've got some users, and some varied experience of using the library, then I think making a library proposal would be a good idea.
I looked through all packages published by you on Hackage (quite a few!) and all of them expect yhccore, proplang, GuiHaskell and firstify depend only on core packages (e.g. base, containers, mtl, etc.). None of the libraries depend on many small non-core package and at least one depends on big packages like gtk. In my experience maintaining all these "fine grained" packages with no or few dependencies is not that difficult. However, maintaining packages with many small dependencies is. In my opinion packages should be on a more coarse grained level than modules. Maybe one per task e.g. gtk for graphics, urllib for client side HTTP, etc. It's also the granularity that is used in other, more powerful packaging managers for Linux. Cheers, Johan

Hello Johan, Wednesday, June 4, 2008, 11:56:01 AM, you wrote:
Well if this is the common agreement then I will withdraw my proposal. Maintaining a single module package floating around is too much effort
i'm agree with Neil in this discussion. previously, we inflated Base package to huge size by allowing to include there everything that someone want to include. it was resulted in splitting up of Base which created a serious maintenance problem the same apply to core packages. while every concrete addition may look interesting and we may believe that there is just one way to do it, later we may end up with huge collection of weakly related functionality with unstable interfaces i prefer to keep these packages in maintained mode - i.e. everything included by general consensus on a basis of thorough investigation, so we may be sure that included functionality is really widely used and will stay unchanged. any experimental modules should go into other places idea of marking modules as experimental looks interesting, but 1) there is no tools to ensure that you don't import those experimental modules so they will become a part of library API anyway 2) i don't think that widely used packages should serve as basis for experiments so, i will prefer if interesting new code will be shared by other ways - wiki, hpaste, darcs repositories, new packages on hackage - TIMTOWTDI -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On 2008-05-31, Don Stewart
It's not wasted work. As far as I know, only Ian advocates against including tests.
Having worked on several data structure libraries, I've found that QuickCheck regularly catches errors that appear, and ensure over the long term that code remains stable.
Ian does have a point that there is a lot of wasted effort. Perhaps the flow can be optimized so that these tests aren't run as often. One would get nearly the same benefit if they're only run right before major distribution, to keep buggy versions from widespread usage. Then, the patch that caused the bug can easily be tracked down by bisection. Even if they're never run automatically on every change, they're a valuable bit of documentation: they're an unambiguous machine-readable specification of several properties that are expected to hold. -- Aaron Denney -><-

igloo:
On Sat, May 31, 2008 at 10:44:40AM +0200, Krasimir Angelov wrote:
I was silent for some time but in this time I created QuickCheck tests for Data.Tree.Zipper which achieve 100% coverage with HPC. I also created a ticket for it: Ticket #2324
http://hackage.haskell.org/trac/ghc/ticket/2324
The attached file is the current implementation and it contains the version updated from Iavor Diatchki. It has the advantage that it also works with forests, not just with trees.
Initially I thought that complete testsuite for such a simple module might be overkill but actually I found a bug :-) in the splitChildren function which is now fixed.
So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
You're on your own on this one, Ian. QuickCheck is a cheap, simple way to get good coverage, that's why Haskell library writers use it. Please include tests, Krasimir! -- Don

On Sat, 2008-05-31 at 10:10 -0700, Don Stewart wrote:
You're on your own on this one, Ian. QuickCheck is a cheap, simple way to get good coverage, that's why Haskell library writers use it.
Please include tests, Krasimir!
Ian does have a point. We're talking about two different testing contexts: * GHC nightly builds * tests run on commits by developers I absolutely agree with you Don about the second context. That's the one eg for bytestring where we found lots of our own stupid mistakes before they caused segfaults for end users. It vital for initial development and for making subsequent changes to the library. On the other hand Ian is quite right that for GHC nightly builds (where you're not actually making any changes to the module) it does seem like a lot of wasted effort to run the same tests again and again. Perhaps we can see a way to run the right tests in the right context. If there have been changes then the full QC testsuite is demanded. If on the other hand we're just looking at a system level integration test then perhaps we do not need to run all the tests at a maximum level of coverage. Perhaps we could take a probabilistic approach. How about a QC test driver that runs say 2 instances of each QC property at the same QC Aribtrary 'size' as you'd hit when you do the full 100 tests. That way each nightly run tests a different sample and we don't just keep hitting the 0/[] cases (though we will still hit 0/[] sometimes, the 'size' parameter is a maximum not minimum). It should still catch the obvious integration bugs (like changed semantics of imported modules). Then we can do 'full' runs at important junctures like release candidates. Duncan

Hello, Just for the record: I agree fully with the opinion expressed here by Ian. Best regards Thorkil On Saturday 31 May 2008 13:16, Ian Lynagh wrote:
On Sat, May 31, 2008 at 10:44:40AM +0200, Krasimir Angelov wrote:
I was silent for some time but in this time I created QuickCheck tests for Data.Tree.Zipper which achieve 100% coverage with HPC. I also created a ticket for it: Ticket #2324
http://hackage.haskell.org/trac/ghc/ticket/2324
The attached file is the current implementation and it contains the version updated from Iavor Diatchki. It has the advantage that it also works with forests, not just with trees.
Initially I thought that complete testsuite for such a simple module might be overkill but actually I found a bug :-) in the splitChildren function which is now fixed.
So just to check, this proposal is to add Data.Tree.Zipper to containers and the QC tests to the testsuite, right?
As I've explained before[1], I don't think that QuickCheck tests are a good way to test libraries: They tend to test the same inputs (e.g. []) or equivalent inputs (e.g. "insert 2 [3]" and "insert 3 [4]") many times, meaning it takes much longer to get the same level of testing as a few well-chosen unit tests. When you multiply this by all the libraries the testsuite is meant to test, this is a significant amount of time.
I also don't think that adding the tests but not running them automatically is a good idea, as they will most likely just bitrot.
Adding a unit test for the bug you found is certainly a good idea, though!
[1] http://www.haskell.org/pipermail/libraries/2008-April/009594.html
Thanks Ian
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
participants (16)
-
Aaron Denney
-
apfelmus
-
Bulat Ziganshin
-
Chris Smith
-
Don Stewart
-
Duncan Coutts
-
Ian Lynagh
-
Iavor Diatchki
-
Isaac Dupree
-
Jean-Philippe Bernardy
-
Johan Tibell
-
Krasimir Angelov
-
Malcolm Wallace
-
Neil Mitchell
-
Ross Paterson
-
Thorkil Naur