
Am Mittwoch, 1. März 2006 01:26 schrieb Alson Kemp:
Although the discussion about Array refactoring died down quickly on the Haskell' mailing list, I've been noodling on refactoring the various Collections in Haskell. In doing so, I've bumped into a problem with type classes that I can't resolve. The issue is as follows:
I'm designing a Collections class heirarchy that is a blend between that of Java and of Haskell. The problem is that, whereas in OOP it is easy to do so, Haskell class mechanism seems to make it difficult to add *new* member variable to subclasses.
Simple goal: create a top-level Collection with an *indexed* Array subclass (and various other subclasses). The problem I'm running into is Collection has no need of an "index" variable and I can't seem to figure out how to add an "index" to Array when subclassing from Collection Mock up:
-- class CollectionClass c e where -- every Collection supports toList... toList :: c e -> [e]
class (CollectionClass a e)=> ArrayClass a e where ...
data Array i e = Array i i ^^^^^^^^^^ shouldn't the element type appear here?
instance CollectionClass Array e where -- Since Array is a Collection -- toList :: c e -> [e] -- but with an Array the type would be -- toList :: a i e -> [e] toList = ...
Well, the parameter c of CollectionClass has kind (* -> *), Array has kind (* -> * -> *), so it must be instance CollectionClass (Array i) e where ... But the element type doesn't really belong in the class, wouldn't class Collection c where toList :: c e -> [e] instance Collection [] where toList = id instance Collection (Array i) where -- or rather instance Ix i => Collection (Array i), -- if we use Data.Array toList = elems -- or whatever we'd use for another implementation class Collection (a i) => ArrayC a i where item :: i -> a i e -> Maybe e -- or perhaps, better class Collection c => ArrayLike c i | c -> i where look :: Monad m => i -> c e -> m e be preferable?
--
I think that the problem goes away if: class CollectionClass c x e where ... with "x" used an index for Array or a key for Map or () for Set, but it doesn't seem clean to scatter member variables in the parent class in case the subclass requires them...
Another possible solution that I couldn't get to work would be to use (Array i) as the type for "c" in
I can't imagine why that wouldn't work (apart from the typo above). It compiles, and if we have a more appropriate Array type, we'd get a decent toList-function.
"Collection c": instance CollectionClass (Array i) e where toList = ... -- (Array i) e -> [e] ?
This seems clean because it says the Collection holds "e"s and is organized by an (Array i). Similarly, Set would be a Collection of "e"s organized by Set and Map would be a Collection of "e"s organized by (Map k).
Undoubtedly, I've missspoken some crucial aspect of the type/kind/class/instance magical incantation. Help!
- Alson
HTH, Daniel -- "In My Egotistical Opinion, most people's C programs should be indented six feet downward and covered with dirt." -- Blair P. Houghton