7
我正在寫一個類似於應用程序的CRUD,並且有很多通過主鍵查找(主鍵可以有不同類型)。所以我定義以下類型類:推測公式類型
{-# LANGUAGE MultiParamTypeClasses #-}
class Eq b => HasPK a b where
getPK :: a -> b
現在我可以這樣寫:
import Data.Maybe
lookupPK :: HasPK a b => b -> [a] -> Maybe a
lookupPK s = listToMaybe . filter ((== s) . getPK)
現在,當我想比較PK兩件事情,我只是想比較它們的PK的。所以,我想這個定義:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
instance (HasPK a b) => Eq a where
(==) = (==) `on` getPK
但現在它給了我:
src/Utils.hs:61:10: Could not deduce (HasPK a b0) …
arising from the ambiguity check for an instance declaration
from the context (HasPK a b)
bound by an instance declaration: HasPK a b => Eq a
at /home/utdemir/workspace/.../Utils.hs:61:10-28
The type variable ‘b0’ is ambiguous
In the ambiguity check for: forall a b. HasPK a b => Eq a
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the instance declaration for ‘Eq a’
Compilation failed.
任何人都可以解釋這個錯誤給我嗎?我在正確的軌道上,還是有更安全的方式來實現我想要的?
是的,在定義了這個實例後,我得到了'src/Utils.hs:52:20:因使用'/ ='而產生的Eq整數的重疊實例... 匹配實例: 實例Eq整數 - 定義在'integer-gmp:GHC.Integer.Type'實例(等式B,HasPK a b)=>等式a'中。但是由於'Integer'沒有'HasPk Integer b'實例,所以我並不期待這個錯誤。如果我定義了Eq和HasPK,我會理解這個錯誤,但是由於沒有'HasPK Integer',它不應該直接使用普通的'Eq'實例嗎? – utdemir 2015-03-13 09:36:37
@utdemir問題是:一個'實例C a => Eq a'適用於每種類型,即使對於那些C a'爲假(!)的類型也適用。 Haskell將承諾使用此實例,並且當'C a'時,它將會出錯,而不是回溯並查找其他實例。這樣做是因爲回溯問題變得更加困難,而Haskell設計人員則關注編譯時間。GHC有一個'OverlappingInstances'擴展,可以放寬這個限制,但我不推薦它。重疊的實例最好避免,恕我直言。 – chi 2015-03-13 09:48:36
謝謝,我選擇了家庭解決方案,因爲它看起來像是一個最沒有爭議的擴展。 – utdemir 2015-03-13 15:16:29