2012-10-26 30 views
1

使用以下類型和類定義,我不明白爲什麼我會在下面創建instance時出錯併發生錯誤。存在類型。爲異構映射編寫類的實例

我需要MyMap來保存異構值的映射。

{-# LANGUAGE ExistentialQuantification #-} 
module Scratch.SO_ExtistentialTypes where 

import Data.Map 

type MyMap a = Map String a 

class MyClass c where 
    getMyMap :: forall a. c -> MyMap a 

data MyData = forall a. MyData { 
    myMap :: MyMap a 
} 

instance MyClass MyData where 
    getMyMap = myMap -- <= ERROR 
+2

你想在這裏完成什麼?因爲我嚴重懷疑這是一個好方法。 –

+0

@ C.A.McCann'type'和'class'是定義'API'的模塊的一部分。 'data'和'type'是(簡化的)暫定實現。 –

+0

@ C.A.McCann另一種說法是:如何創建一個可以作爲MyClass實例的數據類型(MyData)? –

回答

9

一方面,這裏的forall是多餘的:

class MyClass c where 
    getMyMap :: forall a. c -> MyMap a 

沒有明確的綁定類型變量在最外層是普遍定量,所以這是完全一樣,只是c -> MyMap a

除此之外,普遍量化的類型當然不會匹配存在量化類型。 getMyMap的類型表示,如果類型爲c,則對於a類型的任何可能的選擇,它將生成MyMap a類型的值。另一方面,訪問者myMap說,給定值爲MyData的值時,它將產生MyMap a類型的值,用於某些特定但未知的類型a

這是不可能有解開生存類型的漂浮本身(這需要對應forallexists量詞),所以沒有辦法改寫的getMyMap,使得myMap是一種有效的實現類型。

所有你可以用存在類型的東西做的事情都是用另一種隱藏存在量詞的數據類型來包裝它,或者把它賦予一個具有普遍量化類型的參數的函數。例如,您可以在列表[a]上使用length,使用a作爲存在類型。

在你的情況下,Map的值具有存在類型,沒有其他結構或約束,所以它們幾乎沒用,可能是()

+0

非常感謝。我現在明白'getMyMap'類型的定義表達了錯誤的東西(它返回一個* universally *量化類型的Map)。那麼,如何在一個類中表達我需要一個函數來返回一個異構值的Map(如果可能的話)? –

+1

@BGR:表達這種類型是一回事,但更大的問題實際上是使用包含異構類型值的結構。使用這種類型的奧術技術確實存在(哈,哈),但我的經驗法則是「如果你需要問怎麼做,不要」。如果你想要一個理智的API,這不是一個可怕的痛苦,你可能需要一個不同的設計。 –

+0

:)足夠公平。感謝您花時間。 –