[英]Haskell inheriting type classes
假設我有以下課程:
class P a where
nameOf :: a -> String
我想聲明此類的所有實例都是Show
實例。 我的第一次嘗試是:
instance P a => Show a where
show = nameOf
昨天我第一次嘗試使用這種方式導致了語言擴展的混亂:首先被告知要打開靈活的實例,然后打開不確定的實例,然后再打開實例,最后遇到關於重復實例聲明的錯誤。 我放棄並返回重復代碼。 但是,從根本上講,這似乎是一個非常簡單的需求,應該容易滿足。
因此,有兩個問題:
UndecidableInstances
,因為我似乎違反了Paterson條件,但是這里沒有重疊的實例:甚至沒有P
實例。 為什么類型檢查器認為Show Double
有多個實例(在這個玩具示例中似乎就是這種情況)? 之所以會出現重疊實例錯誤,是因為您的P
某些實例可能具有Show
其他實例,然后編譯器將無法決定使用哪個實例。 如果您有一個Double
的P
實例,那么您將獲得Show
for Double
兩個實例:您的常規實例和已經在Haskell基庫中聲明的實例。 @augustss在您的問題注釋中正確說明了如何觸發此錯誤。 有關更多信息,請參見規格 。
如您所知,沒有UndecidableInstances
,就無法實現您正在嘗試的東西。 啟用該標志時,您必須了解您正在承擔編譯器的責任,以確保不會出現任何沖突的實例。 這意味着,當然,您的庫中不得存在其他任何Show
實例。 這也意味着您的庫不會導出P
類,這將消除庫用戶聲明沖突實例的可能性。
如果您的情況與上述內容有沖突,則可以肯定地表明問題一定存在。 實際上有...
首先,您要實現的目標是錯誤的。 您缺少有關Show
類型類的幾點要點,將其與流行的OO語言的toString
方法之類的構造區分開來:
從秀的黑線碼頭 :
show的結果是在語法上正確的Haskell表達式,其中僅包含常量,並且在聲明類型的那一刻使用了固定性聲明。 它僅包含在數據類型,括號和空格中定義的構造函數名稱。 當使用帶標簽的構造函數字段時,還使用大括號,逗號,字段名稱和等號。
換句話說,聲明Show
實例並不會產生有效的Haskell表達式本身是錯誤的。
鑒於上述情況,當類型允許簡單地派生Show
時,聲明Show
的自定義實例就沒有意義。
當某個類型不允許派生它時(例如GADT),通常您仍然必須堅持使用特定於類型的實例來產生正確的結果。
因此,如果您需要自定義表示功能,則不應為此使用Show
。 只需聲明一個自定義類,例如:
class Repr a where
repr :: a -> String
並負責任地處理實例聲明。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.