簡體   English   中英

為什么此Haskell類型類代碼不起作用?

[英]Why doesn't this Haskell typeclass code work?

試圖找出Haskell類型類。 為什么以下工作不起作用?

{-# LANGUAGE FlexibleInstances #-}
class IntClass t
instance IntClass Int

intToIntClass  :: (IntClass r) => Int -> r
intToIntClass  x = x

顯然,“實例”並不代表我認為的含義。 相反,它給出了錯誤消息,我不理解。

Could not deduce (r ~ Int)
from the context (IntClass r)
  bound by the type signature for intToIntClass  :: IntClass r => Int -> r
  at f.hs:10:1-16
  `r' is a rigid type variable bound by
      the type signature for intToIntClass  :: IntClass r => Int -> r
      at f.hs:10:1
In the expression: x
In an equation for `intToIntClass t': intToIntClass  x = x

簽名

intToIntClass  :: (IntClass r) => Int -> r

表示intToIntClass可以產生調用者想要的任何類型的值,只要該類型屬於IntClass 但是實現只能產生Int值。

就編譯器而言,到目前為止, Int是唯一的實例並沒有幫助,在其他模塊中可能定義了更多的實例,因此編譯器無法接受僅生成Int的方法。

您編寫的函數說:“給我點東西,我會把它還給您。” 您寫的類型說:“我可以將Int轉換為調用者想要的任何類型,只要該類型是IntClass類型類的實例IntClass 。”

當我們將它們放在一起時,我們有一個函數將從調用方那里獲取一個Int並將其直接返回。 除了返回相同的Int以外,它將是調用者希望的任何類型的值,只要該類型是IntClass類型類的成員IntClass 輸入如何從Int變為調用者想要的任何(受限)類型? 不可以 由於輸入是直接返回的,因此返回類型必須與參數類型相同。 類型檢查器從您的代碼中推斷出這一點,但隨后將其命名為輸出類型r卻無法調和該推斷。 類型檢查器希望與此一起工作,但是在唯一的假設是rIntClass類型類的實例的情況下,不能確保rInt是同一件事。

類似於您編寫的函數是fromInteger ,位於Num類型類中。 如果您想討論可以基於Int構造的所有類型,那么這應該是您的typeclass的方法。 就像是:

class IntClass a where
  intToIntClass :: Int -> a

您將為要成為IntClass實例的每種類型定義此方法,並具有所需的intToIntClass :: IntClass r => Int -> r 此返回類型多態性嚴重取決於每個參與類型都具有適當的intToIntClass定義。

您的類型分類很好。 例如,這有效:

intId :: IntClass r => r -> r
intId = id

問題是, intToIntClass的類型簽名表明它從Int映射到IntClass 任何成員。 編譯器無法證明IntIntClass唯一成員,因此,由於intToIntClass的主體嚴格返回Int ,因此多態性不夠。

為了進一步說明,假設我將您的模塊與新實例一起使用:

instance IntClass Integer

然后,您對intToIntClass的實現也承諾具有類型(IntClass Integer => Int -> Integer) 但是您的實現與此矛盾。 編譯器假定類型類是“開放的”,這意味着

  1. 將來可能會出現新的實例,並且
  2. 今天的代碼不得在這樣的未來改變行為

因此,編譯器認為今天唯一的實例是Int但不能假設將來會保持這種情況。

(1.)和(2.)的組合使對Haskell代碼的思考和推理更加容易。 當您知道今天的新實例無法破壞昨天的代碼並且今天的代碼對於明天的新實例是安全的時,警告的數量就更少了。

暫無
暫無

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

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