簡體   English   中英

如何處理需要額外類型約束的類型類實例

[英]How to handle a Typeclass Instance requiring additional Type Constraints

我發現自己處於一種情況,我想要定義的類型類實例需要額外的類型約束。 具體來說,我想為一個類型Trie a定義Show

data Trie a = Node {
    label :: a,
    edges :: DM.Map a (Trie a),
    isFinal :: Bool
}

而Show的實例是:

import qualified Data.Tree as DT

instance (Show a, Eq a, Eq (Trie a)) => Show (Trie a) where
    show trie@(Node label edges _) = DT.drawTree (mapTree show $ toDataTree trie)

我在這里需要Eq aEq (Trie a) ,因為我使用toDataTreeTrie a轉換為DT.Tree a並且需要這些類型約束:

import qualified Data.Map as DM

toDataTree :: (Eq a, Eq (Trie a)) => Trie a -> DT.Tree a
toDataTree (Node label edges isFinal)
    | edges == DM.empty = DT.Node label (map toDataTree (DM.elems edges))
    | otherwise = DT.Node label []

mapTree :: (a -> b) -> DT.Tree a -> DT.Tree b
mapTree f (DT.Node rootLabel subForest) = DT.Node (f rootLabel) $ map (mapTree f) subForest

現在,雖然這確實編譯,當我真的想在Trie a上調用print (在這種情況下a = Char )我得到了

• No instance for (Eq (Trie Char)) arising from a use of ‘print’
• In a stmt of an interactive GHCi command: print it

這一定是因為我需要將這些額外的類型約束添加到Show的實例中。 所以我的方法可能是錯的。

類型類實例定義所需的其他類型約束的正確解決方案是什么?

我假設你的程序中的toDataTree守衛有一個錯誤,你的意思是:

| edges /= DM.empty = ...

但是,您不需要Eq實例來檢查映射是否為空。 如果使用DM.null ,則可以從toDataTreeShow實例中刪除Eq約束:

toDataTree :: Trie a -> DT.Tree a
toDataTree (Node label edges isFinal)
    | not (DM.null edges) = DT.Node label 
                             (map toDataTree (DM.elems edges))
    | otherwise = DT.Node label []

實際上,如果地圖為空,那么無論如何映射其元素都會產生一個空列表,因此您可以進一步簡化為:

toDataTree :: Trie a -> DT.Tree a
toDataTree (Node label edges isFinal)
  = DT.Node label (map toDataTree (DM.elems edges))

無論如何,這應該可以解決您當前的問題。

將所有這些設置在一邊,錯誤的原因是您沒有為任何Trie提供任何Eq實例。 您可以在Trie的定義中添加一個deriving (Eq)子句:

data Trie a = Node {
    label :: a,
    edges :: DM.Map a (Trie a),
    isFinal :: Bool
} deriving (Eq)

這可能會給你一個關於脆弱的內部綁定的可怕警告,但你可以從Show實例和toDataTree刪除Eq (Trie a)約束(因為它們將由Eq a約束暗示)以使警告消失。

盡管如此,如上所述,你真的不想這樣做,因為使用DM.null並完全繞過Eq實例是更好的做法。

暫無
暫無

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

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