Class Types Associated Families & # 8594; containers, keys and items: who is who?

Reading about family types in haskellwiki , I see an example

class Collects ce where type Elem ce empty :: ce insert :: Elem ce -> ce -> ce 

This makes sense to me, because I use my (possibly counterproductive) OOP metaphors - an instance of Collects HAS A type (synonym) Elem ce. The collection is somehow more than elements.

I got confused in the example for related data families because it is not suitable for this model.

  class GMapKey k where data GMap k :: * -> * empty :: Gmap kv insert :: k -> v -> GMap kv -> Gmap kv 

The card collects vs and feels "bigger" than vs and ks. But it seems like GMapKey has an associated GMap when I expected relationships to go the other way.

When I choose between data families and types of synonymous families, should I follow the pattern (data families: container is a related type, types of synonyms: element is a related type)? Or is it IS A / HAS The difference does not matter, and two examples could be replaced?

+4
source share
2 answers

I would think of it this way: the GMap family is associated with k , and you should have an instance of the GMap family associated with k for k to be used as GMapKey .

The choice between these options is more dependent on your needs than with anything else. The GMap k approach is preferable when the key type dictates the implementation of the map: for example. use the IntMap keys for Int , but use other Map types for other keys ...

+4
source

The IS A / HAS ratio is a bad metaphor here. The best intuition would be "ASSOCIATIONS S" or "SPECIALIZE (some type)." In practice, this means that with type resolution

 f :: GMapKey k => k -> GMap kv -> v 

both the first and second parameters are polymorphic, but must be combined together. It does not need to be contained inside another.


To decide which “direction” to use, you need to think about how things are generalized. If you define a class of "containers" that associated types for a "key", then you say that each type of container "instantiates this class interface" on a single key. This is a many-to-one relationship, since each container has one associated key, but the keys can be related types for many containers. If you go the other way, you declare that each “key” is limited to a certain type of “container”, but there can be many different keys in containers that can index them.

+4
source

Source: https://habr.com/ru/post/1480267/


All Articles