Re: [Haskell-cafe] where to put general-purpose utility functions
Hi Joey, Apologies for such a late reply. I don't know if others have replied on -cafe; it has become too high-volume for me to follow of late. There are several options. MissingH is one. I have accepted patches there for a long time. Another is that now that Hackage/Cabal foster easy inclusion of small packages, you might want to roll your own. (Occasionally I have hesitation about drive-by commits to MissingH because I get asked to support the code later at times.) -- John On 01/21/2012 02:20 PM, Joey Hess wrote: I'm finding a rather unusual problem as I write haskell.. Unlike every other language I've used, large portions of my haskell code are turning out to be general-purpose, reusable code. Fully 20% of the haskell code I've written for git-annex is general purpose. Now, I came out of a decade of perl with maybe 1% reusable code. So I'm sure this is a credit to haskell, and not to me. My problem now is that as I start new projects, I want to have my haskell utility functions available, and copying them around is not ideal. So, put them on hackage. But where, exactly? It already has several grab bag utility libraries. The only one with much traction is MissingH. Using the others makes a program have an unusual dependency, which while only a cabal install away, would make work for distributions that want to package the program. I've ruled out using a couple on that basis. Doesn't encourage me to add another one. My 2000+ lines of reusable code are a grab-bag of generic utility functions. Looking them over (see Appendix), I could try to get portions into existing libraries on hackage, but it's unlikely I'd find a home for most of them, so I'm still left with this problem of what to do. I wonder if the model used for xmonad-contrib, of a big library package, that is very open to additions from contributors, would be helpful here? John, any interest in moving MissingH in this direction? I get the impression it's not otherwise changing much lately, and parts of it are becoming naturally obsolete, maybe this could inject some life into it. Any other thoughts you have on grab-bag utility libraries on hackage also appreciated. Appendix: A sample of a a few of the better functions from my utility library. Some quite generic monadic control functions, few of them truely unique: whenM :: Monad m = m Bool - m () - m () -- also? unlessM :: Monad m = m Bool - m () - m () -- also! firstM :: Monad m = (a - m Bool) - [a] - m (Maybe a) A module that exports functions conflicting with partial functions in the Prelude, to avoid them being accidentially used. And provides some alternatives (which overlap somewhat with Safe): headMaybe :: [a] - Maybe a readMaybe :: Read a = String - Maybe a beginning :: [a] - [a] Various path manipulation functions such as: dirContains :: FilePath - FilePath - Bool dotfile :: FilePath - Bool absPath :: FilePath - IO FilePath Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) catchMaybeIO :: IO a - IO (Maybe a) readSize :: [Unit] - String - Maybe ByteSize -- parses 100 kb etc format :: Format - Variables - String findPubKeys :: String - IO GpgKeyIds boolSystem :: FilePath - [CommandParam] - IO Bool withTempFile :: Template - (FilePath - Handle - IO a) - IO a ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
That is one of the wonderful things about haskell, most languages have a negative correlation between codesize and productivity, however with haskell there is a strong positive correlation. You can re-use so much that as your code base grows it becomes easier to add new features rather than harder. I solve that problem by having a darcs repository for all my utility modules, then when I want to use them in a project, I just 'darcs pull' them into the current repository and they appear. as long as a patch doesn't cross the boundry between the utility modules and the rest of the codebase I can push changes upstream to the utility repository from my specific project, or pull in new improvements to the utility functions. I can also make local modifications to the utility modules and just not push the local modifications upstream if needed. The cool thing is that the darcs history has the merged history of my projects, and tagging with a version number or release will snapshot both your program and the exact version of the utility routines used at that time. The ability to have multiple sibling darcs repositories is a really powerful feature. quite handy. I had a similar system before darcs where I used a shared RCS directory between projects, but that wasn't nearly as seamless or integrated. Plus it makes it easier when collaborating, as far as anyone is concerned, the project is a single darcs repository they can get and build and create patches for. The fact that behind the scenes it is actually a collection of repositories spawning patches. modifying them, and exchanging them in a bizarre parody of bacterial plasmid exchange* is completely transparent. John * stolen prose, I just liked the sound of it. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
On Mon, Jan 23, 2012 at 1:01 PM, Joey Hess j...@kitenet.net wrote: Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) Is this partition from Data.List? No; it's like break but does not include the separating character in the snd list. I like let (hd, _ : tl) = break prd lst in... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
On Tue, Jan 24, 2012 at 1:00 PM, David Fox dds...@gmail.com wrote: On Mon, Jan 23, 2012 at 1:01 PM, Joey Hess j...@kitenet.net wrote: Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) Is this partition from Data.List? No; it's like break but does not include the separating character in the snd list. I like let (hd, _ : tl) = break prd lst in... Oh, wait. That won't always work. :( ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
I like let (hd, _ : tl) = break prd lst in... Oh, wait. That won't always work. :( second (drop 1) . break prd list? :) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
Hi, On 21.01.2012, at 21:20, Joey Hess wrote: My problem now is that as I start new projects, I want to have my haskell utility functions available, and copying them around is not ideal. So, put them on hackage. But where, exactly? It already has several grab bag utility libraries. The only one with much traction is MissingH. Using the others makes a program have an unusual dependency, which while only a cabal install away, would make work for distributions that want to package the program. I've ruled out using a couple on that basis. Doesn't encourage me to add another one. My 2000+ lines of reusable code are a grab-bag of generic utility functions. Looking them over (see Appendix), I could try to get portions into existing libraries on hackage, but it's unlikely I'd find a home for most of them, so I'm still left with this problem of what to do. I wonder if the model used for xmonad-contrib, of a big library package, that is very open to additions from contributors, would be helpful here? John, any interest in moving MissingH in this direction? I get the impression it's not otherwise changing much lately, and parts of it are becoming naturally obsolete, maybe this could inject some life into it. Any other thoughts you have on grab-bag utility libraries on hackage also appreciated. Personally, I've always been avoiding those grab-bags of functionality like MissingH and other libraries. Not because I think they don't provide anything useful. But, because their level of maintenance is not clear to me. A rather large library of utility functions tends to need many dependencies on other hackage packages. That makes the question of maintenance even more important. As others have pointed out some of your functions may already exist in some widely used package. And other might be easy to be replaced by some idiom. Don't underestimate the depth of Haskell and it's well thought libraries. I am regularly amazed by finding some new way to combine seemingly trivial functions to do some non-trivial task. Every time that happens I can remove some of my utility functions. Therefore, I would reuse my own collection of utility code as a separate repository to be included as a sub repository in other projects. Mercurial and Git support that very well, I am not sure about darcs' support for that. This approach allows you to avoid copypaste reuse and it allows you to evolve your personal collection at your speed without worrying for backwards compatibility or API changes. Publishing a library on hackage comes --- at least in an ideal world --- with some commitment to document it, keep it compiling and working with a set of compiler and library permutations, fix bugs and so on. In short it comes with a commitment to maintain it. At least for some time. If you would just like to drop some pile of code in hope someone will find it useful. Do that, but perhaps there might be better places for that than hackage. Cheers, Jean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
David Fox wrote: I try to create a workflow for this sort of thing. I create a package with a name like set-extra, with one module Data.Set.Extra and an alternative Data.Set module that exports both the old Data.Set and the symbols in Data.Set.Extra. Then I email the maintainers of the Containers package with a suggestion. After a while I upload set-extra to hackage if I need to use set-extra in another hackage package. Thanks, that's the most helpful hint. It matches MissingH's use of .Utils modules too. Jean-Marie Gaillourdet wrote: Personally, I've always been avoiding those grab-bags of functionality like MissingH and other libraries. Not because I think they don't provide anything useful. But, because their level of maintenance is not clear to me. A rather large library of utility functions tends to need many dependencies on other hackage packages. That makes the question of maintenance even more important. It's not clear to me either. I used MissingH starting out because I personally know and trust John and/or he cowrote RWH. Don't know that I would have otherwise. (And I only use Data.String.Utils, System.Cmd.Utils, and Data.Bits.Utils from it.) As others have pointed out some of your functions may already exist in some widely used package. And other might be easy to be replaced by some idiom. Don't underestimate the depth of Haskell and it's well thought libraries. I am regularly amazed by finding some new way to combine seemingly trivial functions to do some non-trivial task. Every time that happens I can remove some of my utility functions. Well, this is certianly true, on the other hand then you end up with a pattern of repeatedly combining some trivial functions in a certian way, and it then makes sense to formalize that. It's better to have `fromMaybe` than to repeatedly use `id` with `maybe`. Tristan Ravitch wrote: whenM :: Monad m = m Bool - m () - m () -- also ? unlessM :: Monad m = m Bool - m () - m () -- also ! firstM :: Monad m = (a - m Bool) - [a] - m (Maybe a) IfElse (http://hackage.haskell.org/packages/archive/IfElse/0.85/doc/html/Control-Monad-IfElse.html) has a few of these. whenM is in a dozen packages, the others fewer but scattered here and there. I also found ? and ! somewhere on hackage once but not sure where. Various path manipulation functions such as: absPath :: FilePath - IO FilePath Is this different from canonicalizePath in directory? Yes; it doesn't require the path to exist. Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) Is this partition from Data.List? No; it's like break but does not include the separating character in the snd list. format :: Format - Variables - String This looks like it might be similar to HStringTemplate This particular format allows for things like ${foo} ${bar;10} ${baz;-10}\n so it's sort of printf like, but not entirely. withTempFile :: Template - (FilePath - Handle - IO a) - IO a temporary (http://hackage.haskell.org/packages/archive/temporary/1.1.2.3/doc/html/System-IO-Temp.html) has a few variants of this one Indeed, however all its functions can fail if getTemporaryDirectory fails; this one puts the temp file in . in that case. Simon Hengel wrote: headMaybe :: [a] - Maybe a Is this the same as Data.Maybe.maybeToList? Rather listToMaybe.. it is the same as that in fact. Though I also have a lastMaybe that does not have an equivilant in Data.Maybe. readMaybe :: Read a = String - Maybe a This has been added to base recently [1]. Great! Although there are multiple ways to choose to implement this. I found it useful to make it succeed even if not all the string was consumed, or when there are multiple valid results. I've renamed mine readish. -- eee shy jo signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
I try to create a workflow for this sort of thing. I create a package with a name like set-extra, with one module Data.Set.Extra and an alternative Data.Set module that exports both the old Data.Set and the symbols in Data.Set.Extra. Then I email the maintainers of the Containers package with a suggestion. After a while I upload set-extra to hackage if I need to use set-extra in another hackage package. On Sat, Jan 21, 2012 at 12:20 PM, Joey Hess j...@kitenet.net wrote: I'm finding a rather unusual problem as I write haskell.. Unlike every other language I've used, large portions of my haskell code are turning out to be general-purpose, reusable code. Fully 20% of the haskell code I've written for git-annex is general purpose. Now, I came out of a decade of perl with maybe 1% reusable code. So I'm sure this is a credit to haskell, and not to me. My problem now is that as I start new projects, I want to have my haskell utility functions available, and copying them around is not ideal. So, put them on hackage. But where, exactly? It already has several grab bag utility libraries. The only one with much traction is MissingH. Using the others makes a program have an unusual dependency, which while only a cabal install away, would make work for distributions that want to package the program. I've ruled out using a couple on that basis. Doesn't encourage me to add another one. My 2000+ lines of reusable code are a grab-bag of generic utility functions. Looking them over (see Appendix), I could try to get portions into existing libraries on hackage, but it's unlikely I'd find a home for most of them, so I'm still left with this problem of what to do. I wonder if the model used for xmonad-contrib, of a big library package, that is very open to additions from contributors, would be helpful here? John, any interest in moving MissingH in this direction? I get the impression it's not otherwise changing much lately, and parts of it are becoming naturally obsolete, maybe this could inject some life into it. Any other thoughts you have on grab-bag utility libraries on hackage also appreciated. Appendix: A sample of a a few of the better functions from my utility library. Some quite generic monadic control functions, few of them truely unique: whenM :: Monad m = m Bool - m () - m () -- also ? unlessM :: Monad m = m Bool - m () - m () -- also ! firstM :: Monad m = (a - m Bool) - [a] - m (Maybe a) A module that exports functions conflicting with partial functions in the Prelude, to avoid them being accidentially used. And provides some alternatives (which overlap somewhat with Safe): headMaybe :: [a] - Maybe a readMaybe :: Read a = String - Maybe a beginning :: [a] - [a] Various path manipulation functions such as: dirContains :: FilePath - FilePath - Bool dotfile :: FilePath - Bool absPath :: FilePath - IO FilePath Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) catchMaybeIO :: IO a - IO (Maybe a) readSize :: [Unit] - String - Maybe ByteSize -- parses 100 kb etc format :: Format - Variables - String findPubKeys :: String - IO GpgKeyIds boolSystem :: FilePath - [CommandParam] - IO Bool withTempFile :: Template - (FilePath - Handle - IO a) - IO a -- see shy jo ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] where to put general-purpose utility functions
I'm finding a rather unusual problem as I write haskell.. Unlike every other language I've used, large portions of my haskell code are turning out to be general-purpose, reusable code. Fully 20% of the haskell code I've written for git-annex is general purpose. Now, I came out of a decade of perl with maybe 1% reusable code. So I'm sure this is a credit to haskell, and not to me. My problem now is that as I start new projects, I want to have my haskell utility functions available, and copying them around is not ideal. So, put them on hackage. But where, exactly? It already has several grab bag utility libraries. The only one with much traction is MissingH. Using the others makes a program have an unusual dependency, which while only a cabal install away, would make work for distributions that want to package the program. I've ruled out using a couple on that basis. Doesn't encourage me to add another one. My 2000+ lines of reusable code are a grab-bag of generic utility functions. Looking them over (see Appendix), I could try to get portions into existing libraries on hackage, but it's unlikely I'd find a home for most of them, so I'm still left with this problem of what to do. I wonder if the model used for xmonad-contrib, of a big library package, that is very open to additions from contributors, would be helpful here? John, any interest in moving MissingH in this direction? I get the impression it's not otherwise changing much lately, and parts of it are becoming naturally obsolete, maybe this could inject some life into it. Any other thoughts you have on grab-bag utility libraries on hackage also appreciated. Appendix: A sample of a a few of the better functions from my utility library. Some quite generic monadic control functions, few of them truely unique: whenM :: Monad m = m Bool - m () - m () -- also ? unlessM :: Monad m = m Bool - m () - m () -- also ! firstM :: Monad m = (a - m Bool) - [a] - m (Maybe a) A module that exports functions conflicting with partial functions in the Prelude, to avoid them being accidentially used. And provides some alternatives (which overlap somewhat with Safe): headMaybe :: [a] - Maybe a readMaybe :: Read a = String - Maybe a beginning :: [a] - [a] Various path manipulation functions such as: dirContains :: FilePath - FilePath - Bool dotfile :: FilePath - Bool absPath :: FilePath - IO FilePath Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) catchMaybeIO :: IO a - IO (Maybe a) readSize :: [Unit] - String - Maybe ByteSize -- parses 100 kb etc format :: Format - Variables - String findPubKeys :: String - IO GpgKeyIds boolSystem :: FilePath - [CommandParam] - IO Bool withTempFile :: Template - (FilePath - Handle - IO a) - IO a -- see shy jo signature.asc Description: Digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
On 2012-01-21 16.20.25 -0400, Joey Hess wrote: My problem now is that as I start new projects, I want to have my haskell utility functions available, and copying them around is not ideal. So, put them on hackage. But where, exactly? Instead of putting all of them in one package, how about you group them into multiple relevant packages. That way we can search for them more easily, have smaller, more meaningful imports, and so on. Sometimes they may make sense as pull requests against other packages, instead. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
You might find many of these on hackage in various forms already.. it might be easier to just depend on some of those libraries. On Sat, Jan 21, 2012 at 04:20:25PM -0400, Joey Hess wrote: Some quite generic monadic control functions, few of them truely unique: whenM :: Monad m = m Bool - m () - m () -- also ? unlessM :: Monad m = m Bool - m () - m () -- also ! firstM :: Monad m = (a - m Bool) - [a] - m (Maybe a) IfElse (http://hackage.haskell.org/packages/archive/IfElse/0.85/doc/html/Control-Monad-IfElse.html) has a few of these. Various path manipulation functions such as: absPath :: FilePath - IO FilePath Is this different from canonicalizePath in directory? Other stuff: separate :: (a - Bool) - [a] - ([a], [a]) Is this partition from Data.List? format :: Format - Variables - String This looks like it might be similar to HStringTemplate withTempFile :: Template - (FilePath - Handle - IO a) - IO a temporary (http://hackage.haskell.org/packages/archive/temporary/1.1.2.3/doc/html/System-IO-Temp.html) has a few variants of this one pgpJEP0MrWorv.pgp Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
headMaybe :: [a] - Maybe a Is this the same as Data.Maybe.maybeToList? readMaybe :: Read a = String - Maybe a This has been added to base recently [1]. Cheers, Simon [1] https://github.com/ghc/packages-base/commit/0e1a02b96cfd03b8488e3ff4ce232466d6d5ca77 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
One thing I found useful when looking if a function already exists under a different name is to use Hayoo to search for the type, i.e.: http://holumbus.fh-wedel.de/hayoo/hayoo.html#0:(a%20-%3E%20Bool)%20-%3E%20%5Ba%5D%20-%3E%20(%5Ba%5D%2C%5Ba%5D) - Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
There is also Hoogle, pretty equivalent I guess. http://www.haskell.org/hoogle/ Thiago. 2012/1/21 Christoph Breitkopf chbreitk...@googlemail.com: One thing I found useful when looking if a function already exists under a different name is to use Hayoo to search for the type, i.e.: http://holumbus.fh-wedel.de/hayoo/hayoo.html#0:(a%20-%3E%20Bool)%20-%3E%20%5Ba%5D%20-%3E%20(%5Ba%5D%2C%5Ba%5D) - Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] where to put general-purpose utility functions
On Sat, Jan 21, 2012 at 11:08 PM, Christoph Breitkopf chbreitk...@googlemail.com wrote: One thing I found useful when looking if a function already exists under a different name is to use Hayoo to search for the type, i.e.: Uh - please ignore the bogus link - I had blindly assumed that it would show my search results. Just use http://holumbus.fh-wedel.de/hayoo/hayoo.html to search for (a - Bool) - [a] - ([a],[a]), for eaxample, and it will find break, span, partiion, etc. - Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe