簡體   English   中英

Haskell繼承類型類

[英]Haskell inheriting type classes

假設我有以下課程:

class P a where
  nameOf :: a -> String

我想聲明此類的所有實例都是Show實例。 我的第一次嘗試是:

instance P a => Show a where
  show = nameOf

昨天我第一次嘗試使用這種方式導致了語言擴展的混亂:首先被告知要打開靈活的實例,然后打開不確定的實例,然后再打開實例,最后遇到關於重復實例聲明的錯誤。 我放棄並返回重復代碼。 但是,從根本上講,這似乎是一個非常簡單的需求,應該容易滿足。

因此,有兩個問題:

  1. 有沒有一種我剛才錯過的簡單方法?
  2. 為什么會出現重疊實例問題? 我可以看到為什么我可能需要UndecidableInstances ,因為我似乎違反了Paterson條件,但是這里沒有重疊的實例:甚至沒有P實例。 為什么類型檢查器認為Show Double有多個實例(在這個玩具示例中似乎就是這種情況)?

之所以會出現重疊實例錯誤,是因為您的P某些實例可能具有Show其他實例,然后編譯器將無法決定使用哪個實例。 如果您有一個DoubleP實例,那么您將獲得Show for Double兩個實例:您的常規實例和已經在Haskell基庫中聲明的實例。 @augustss在您的問題注釋中正確說明了如何觸發此錯誤。 有關更多信息,請參見規格

如您所知,沒有UndecidableInstances ,就無法實現您正在嘗試的東西。 啟用該標志時,您必須了解您正在承擔編譯器的責任,以確保不會出現任何沖突的實例。 這意味着,當然,您的庫中不得存在其他任何Show實例。 這也意味着您的庫不會導出P類,這將消除庫用戶聲明沖突實例的可能性。

如果您的情況與上述內容有沖突,則可以肯定地表明問題一定存在。 實際上有...


首先,您要實現的目標是錯誤的。 您缺少有關Show類型類的幾點要點,將其與流行的OO語言的toString方法之類的構造區分開來:

  1. 秀的黑線碼頭

    show的結果是在語法上正確的Haskell表達式,其中僅包含常量,並且在聲明類型的那一刻使用了固定性聲明。 它僅包含在數據類型,括號和空格中定義的構造函數名稱。 當使用帶標簽的構造函數字段時,還使用大括號,逗號,字段名稱和等號。

    換句話說,聲明Show實例並不會產生有效的Haskell表達式本身是錯誤的。

  2. 鑒於上述情況,當類型允許簡單地派生Show時,聲明Show的自定義實例就沒有意義。

  3. 當某個類型不允許派生它時(例如GADT),通常您仍然必須堅持使用特定於類型的實例來產生正確的結果。

因此,如果您需要自定義表示功能,則不應為此使用Show 只需聲明一個自定義類,例如:

class Repr a where
  repr :: a -> String

並負責任地處理實例聲明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM