2013-05-11 64 views
4

閱讀有關type families on haskellwiki,我看到的例子類型類,相關係列 - >容器,鍵和元素:誰是誰?

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

這對我來說很有意義,因爲我用我的(可能適得其反)OOP的隱喻 - 收集的實例有一個相關聯的類型(代名詞)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,當我預期關係走向另一條路時。

當我在數據族和類型同義詞族之間進行選擇時,這是遵循的模式(數據族:容器是關聯類型,類型同義詞族:元素是關聯類型)?或者這是否與A/HAS的區別無關緊要,這兩個例子是否可以互換?

回答

4

我建議的這樣去想:在GMap家庭與k相關的,你必須有kk相關的GMap型家庭實例被用作GMapKey

這些選項之間的選擇更依賴於您的需求。當鍵類型指示地圖實現時,GMap k方法是優選的:例如,使用IntMapInt鍵,但使用另一種類型的Map用於其他鍵...

+0

謝謝路易斯,這很有道理。我可能錯過了這一點,因爲我面前的用例並不涉及不同鍵的不同實現。我只使用類型族來避免本來是具有函數依賴關係的多參數類型類。 – ImAlsoGreg 2013-05-11 19:22:53

+0

@ImAlsoGreg我衷心贊同避免使用多參數類型類/函數依賴關係。類型家庭更好。 – AndrewC 2013-05-11 20:54:40

4

IS/HAS關係在這裏是一個不好的隱喻。更好的直覺將是「與...聯繫」或「特殊(某種)TO」。在實踐中這意味着,當你解決型

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

第一和第二參數是多態的,但必須統一一起。一個被包含在另一箇中是沒有必要的。


要決定使用哪個「方向」,您必須考慮事物如何概括。如果您定義了一類與「鍵」關聯的「容器」類,那麼您就是說每個容器類型都在一個鍵上「實例化這個類接口」。這是多對一的關係,因爲每個「容器」都有一個關聯的「關鍵字」,但「關鍵字」可以是許多容器的關聯類型。如果換個角度來看,你說每個「鍵」都限制在一個特定類型的「容器」中,但容器可能有許多不同的鍵可以爲它們編制索引。

+0

謝謝。我會試着記住這個助記符,直到更深的直覺陷入:) – ImAlsoGreg 2013-05-12 02:29:22

+0

更多地瞭解Typeclasses是如何工作的一種方法是調查Prolog。類型統一,類型統一和邏輯編程都是類似的範例。 – 2013-05-12 18:52:15