[Haskell-beginners] How to avoid repeating code

Daniel Fischer daniel.is.fischer at googlemail.com
Fri May 27 20:00:19 CEST 2011


On Friday 27 May 2011 19:23:54, Federico Mastellone wrote:
> Now I have a new problem, it's getting really difficult to program
> generically and to create highly parameterized libraries.

Yes.

> 
> So far so good with type families, but when I want to return a generic
> Set for the getValues function and provide a default implementation for
> getValuesCount function I don't know how to do it, I don't even know if
> it is possible.

You can't return a generic Set in getValues (unless you jump through a lot 
of hoops, IntMultiMap has IntSets, so you'd have to transform those to 
Sets, ... yuck) and default implementations wouldn't be possible [or at 
least rather horrible], but

> 
> newtype MultiMap k v = MultiMap (Map.Map k (Set.Set v))
> 
> newtype IntMultiMap = IntMultiMap (IntMap.IntMap IntSet.IntSet)

class (Ord (Elem c)) => Collection c where
  type Elem c
  emtpy :: c
  singleton :: Elem c -> c
  size :: c -> Int
  null :: c -> Bool
  member :: Elem c -> c -> Bool
  ...

> 
> class MultiMapClass m where

class (Collection (Coll m)) => MultiMapClass m where

>  type Key m
>  type Value m

  type Coll m

>  empty :: m
>  addValue :: Key m -> Value m -> m -> m
>  getValues :: Key m -> m -> Set (Value m)

  getValues :: Key m -> m -> Coll m

>  getValueCount :: Key m -> m -> Int
>  getValueCount k m = Set.size $ getValues k m

  getValueCount k m = size (getValues k m)

Should work or be possible to make working.
But things get more complicated the more generic functionality you want to 
add.

It would probably be possible to get a more elegant implementation if you 
designed the library to use a class-based interface from the ground up 
(take a look at the edison library [EdisonAPI and EdisonCore on hackage] 
for an idea of how to structure the classes - edison is old, it was created 
long before type families or functional dependencies were available, I 
don't know what new stuff was incorporated into it, I suspect not too much, 
so you could probably improve the design with the new powerful tools at 
your hands, but as a source of inspiration, it should still serve well).

The problem is that, as a rule of thumb, class based genericity costs 
performance. And the point of the containers package was to provide 
performant data structures, the genericity was wilfully forsaken.

So, perhaps writing a generic envelope for the containers types might not 
be the best option. It could be better to start from a clean sheet.
[disclaimer: I have not thought about how to do that, nor looked at the API 
or implementation from that point of view, so my hunch may be quite wrong.]

Cheers,
Daniel




More information about the Beginners mailing list