Re: [Haskell-cafe] container-classes (was: Restricted type classes)

I'd like to make one more argument in favor of my preference for more splitting of type classes. IMO it's beneficial to split up classes to minimize unnecessary dependencies. That is, while e.g. Monoid is very useful for containers, many container methods won't need it, e.g. "elem" or "filter". When you divide the type classes so only what's necessary is required, more data structures will be able to meet those criteria, which in turn makes the class more generally useful. As an example, I have an extension to iteratee which uses raw buffers for holding data. This allows it to operate in truly constant memory (only one allocation, deallocated when it's finished), which has resulted in performance benefits. Unfortunately there is not a good Monoid instance for this type because appending buffers is not possible. By introducing the NullPoint class (equivalent to mempty of Monoid) in iteratee, my raw buffer extension is able to re-use several iteratee functions which it would not be able to if I had require Monoid instead of NullPoint. I think I've made my arguments as well as I can, so I'm going to be quiet now unless something new comes up. Cheers, John

On 7 September 2010 02:53, John Lato
I'd like to make one more argument in favor of my preference for more splitting of type classes. IMO it's beneficial to split up classes to minimize unnecessary dependencies. That is, while e.g. Monoid is very useful for containers, many container methods won't need it, e.g. "elem" or "filter". When you divide the type classes so only what's necessary is required, more data structures will be able to meet those criteria, which in turn makes the class more generally useful.
Well, my current work is to implement restricted versions of the various type classes (I'm undecided if they should be split off into a separate package or not) and then have the Data.Containers module basically define type aliases (which will probably still use Monoid though, since the vast majority of containers are able to be empty).
As an example, I have an extension to iteratee which uses raw buffers for holding data. This allows it to operate in truly constant memory (only one allocation, deallocated when it's finished), which has resulted in performance benefits. Unfortunately there is not a good Monoid instance for this type because appending buffers is not possible. By introducing the NullPoint class (equivalent to mempty of Monoid) in iteratee, my raw buffer extension is able to re-use several iteratee functions which it would not be able to if I had require Monoid instead of NullPoint.
Hmmm, splitting up Monoid might make sense. I'll have a think about that (I was going to just keep Monoid as is since no constraints are needed. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On 9/6/10 11:46 PM, Ivan Lazar Miljenovic wrote:
Well, my current work is to implement restricted versions of the various type classes (I'm undecided if they should be split off into a separate package or not) and then have the Data.Containers module basically define type aliases (which will probably still use Monoid though, since the vast majority of containers are able to be empty). [...] Hmmm, splitting up Monoid might make sense. I'll have a think about that (I was going to just keep Monoid as is since no constraints are needed.
Bear in mind that splitting up Monoid also means you can define a(n additive) Semigroup class for non-nullable types. I think that's a step in the right direction since it lets you include common 'exotic' collections like non-empty lists. -- Live well, ~wren

On 9/6/10 12:53 PM, John Lato wrote:
I'd like to make one more argument in favor of my preference for more splitting of type classes.
FWIW, I agree that more splitting is generally good. This is one of the problems I have with the various proposals for a ListLike class. They conflate the cons-list like, sequence like, string like, set like (i.e., Boolean algebra), and collection like (e.g., filterable) functions with nary a care. This in turn means that fewer types can implement the class, and moreover that we can state fewer properties about the instances which are there (e.g., what their running time complexity is or should be). The countervailing force, for me, is the question of whether the smaller classes can still be well-defined--- as discussed separately in the "Pointed" thread fork. If MPTCs are involved, the other consideration is to make sure that type inference for common usage isn't borked by splitting things. Even though it's a common argument from others, I don't care about defining one instance with five methods vs five instances with one method each. This last argument seems to be one of the leading problems with redefining the numeric hierarchy. -- Live well, ~wren
participants (3)
-
Ivan Lazar Miljenovic
-
John Lato
-
wren ng thornton