4

在 haskellwiki 上阅读类型族,我看到了这个例子

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

这对我来说很有意义,因为我使用了我的(可能适得其反的)OOP 隐喻——Collects 的一个实例具有关联类型(同义词)Elem ce。该系列在某种程度上比元素“更大”。

我对关联数据系列的示例感到困惑,因为它不适合该模型。

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

该地图收集了vs,感觉比vs和ks“更大”。但似乎 GMapKey 有一个关联的 GMap,当我期望关系走向另一个方向时。

当我在数据系列和类型同义词系列之间进行选择时,这是要遵循的模式吗(数据系列:容器是关联类型,类型同义词系列:元素是关联类型)?还是这 IS A / HAS A 区别无关紧要,这两个例子可以互换?

4

2 回答 2

4

我建议这样考虑:GMap家庭与 关联k,并且您必须有一个与forGMap关联的类型家庭实例才能用作.kkGMapKey

这些选项之间的选择比其他任何事情都更取决于您的需求。当键类型指示映射实现时,该GMap k方法更可取:例如,使用IntMapforInt键,但使用另一种类型的Mapfor 其他键...

于 2013-05-11T18:52:18.163 回答
4

IS A/HAS A 关系在这里是一个不好的比喻。更好的直觉是“关联”或“专门化(某种类型)到”。在实践中,这意味着当您解析类型时

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

第一个和第二个参数都是多态的,但必须统一在一起。没有必要将一个包含在另一个中。


要决定使用哪个“方向”,您必须考虑事物如何概括。如果您定义一个与“键”相关联的类型的“容器”类,那么您就是说每个容器类型在单个键上“实例化此类接口”。这是一个多对一的关系,因为每个“容器”都有一个关联的“键”,但“键”可以是许多容器的关联类型。如果换一种方式,则说明每个“键”都限制为特定类型的“容器”,但容器可能有许多不同的键可以索引它们。

于 2013-05-11T18:52:47.757 回答