2017-09-07 140 views
2
class (Eq k, Ord k, Show k) => KEY k where 
    keyBuild :: NumId -> NumId -> NumId -> k 
    keyDummy :: k 
    keyFromList :: [NumId] -> k 
    -- keyGenerate :: (DATAPOOL p) => p -> Int -> [k] -- p = Pool k e s 


newtype PrimaryKey = PK (NumId, NumId, NumId) deriving (Eq, Ord, Show) 

instance KEY PrimaryKey where 
    keyBuild k0 k1 k2 = PK (k0,k1,k2) 
    keyDummy   = PK (0,0,0) 
    keyFromList is = keyFromList (take 3 (is ++ (replicate 3 0))) 
    keyGenerate p cnt = let 
         ks = keys p 
         pks = map (\l -> keyFromList (randomize l))     (replicate cnt 3) 
         in pks 

我做不能從一個實例函數顯示結果ghci中

let k1 = keyBuild 1 2 3 
let k2 = PK (1,2,3) 
k1 == k2 
True 
k2 
PK (1,2,3) 

,並獲得真正的和預期的k2的值,但

k1 
231:1: error: 
    • Ambiguous type variable ‘a0’ arising from a use of ‘it’ 
     prevents the constraint ‘(KEY a0)’ from being solved. 
     Probable fix: use a type annotation to specify what ‘a0’ should be. 
     These potential instance exist: 
     instance [safe] KEY PrimaryKey -- Defined at Work 

預期PK(1, 2,3) PrimaryKey派生(Eq,Ord,Show)所以我做錯了什麼或錯過了什麼?

+0

NumId = Int在測試 – EntroKay

回答

4

您還沒有給出​​的固定類型。因爲keyBuild可以使用正確的實例構造任何類型的密鑰,所以它具有多態類型k1 :: KEY k => k。這很好,因爲你可以再比較​​不同的具體類型的鑰匙......你的情況,你有k2 :: PrimaryKey嘗試過,但你也可以同樣做k1 == k3k3 :: SomeOtherKeyType,提供SomeOtherKeyType也是KEY類的一個實例 - 在這種情況下,​​也只會「接管」SomeOtherKeyType這一類型。

另一方面是​​沒有特別是類型。它實際上可能是任何適用的類型,但編譯器應該如何知道你想要的?當使用==時,它的兩側必須是相同的類型,所以在一側有足夠的混凝土類型,但其本身​​不明確。

恰巧在你的模塊中只有一個匹配的實例,即KEY PrimaryKey,但通常會有很多(或零!)這樣的實例。如果編譯器只是任意挑選了一個,會不會很奇怪,不是嗎?

所以如果你想顯示​​,你需要手動選擇一種類型。容易做到,只需添加一個本地簽名:

*Main> let k1 = keyBuild 1 2 3 
*Main> :t k1 
k1 :: KEY k => k 
*Main> k1 :: PrimaryKey 
PK (1,2,3) 
+0

非常感謝,還有很多需要學習和理解。 – EntroKay