2012-10-24 66 views
1

我有一個遞歸數據定義:遞歸實例定義

data Checked a = forall b. Checked (Either (Warning, Maybe (Checked b), a) a) 

我需要定義顯示遞歸:

instance (Show a) => Show (Checked a) where 
    show (Right v) = show v 
    show (Left (w, Nothing, v) = show w ++ show v 
    show (Left (w, Just ch, v) = show w ++ show v ++ "caused by" ++ show ch --recursive here 

GHC給

Could not deduce (Show b) arising from a use of `show' 
    from the context (Show a) 
    bound by the instance declaration at Checked.hs:29:10-35 
    Possible fix: 
    add (Show b) to the context of 
    the data constructor `Checked' 
    or the instance declaration 
    In the second argument of `(++)', namely `show ch' 

如果我添加(顯示B)根據實例定義的限制,GHC給出:

Ambiguous constraint `Show b' 
    At least one of the forall'd type variables mentioned by the constraint 
    must be reachable from the type after the '=>' 
In the instance declaration for `Show (Checked a)' 

有沒有下一步我應該採取這個編譯?

+0

請注意,@HaskellElephant已糾正你的代碼(這確實應該在回答中,而不是在你的問題上公佈)。 – AndrewC

+0

@AndrewC我認爲這個錯誤與問題沒有任何關係,所以我糾正了它。我應該恢復它嗎?修復由Sjoerd Visschers解答覆蓋。 – HaskellElephant

+0

@HaskellElephant。我自己幾乎恢復了它,但想讓你有機會將你的編輯作爲答案的一部分。如果你恢復它,在Sjoerd的答案中添加一行以解釋「Checked」應該在那裏。 (目前還不清楚Sjoerd是否看到了原始版本或編輯過的版本)。我認爲在答案中編輯簡單明顯的錯誤是可以的,但如果您不告訴提問者編輯問題,他們可能不會注意到它們將留在不必要的黑暗。如果您還原了,請再次回覆我,以便我可以刪除我的評論。 – AndrewC

回答

5

您需要的Show b限制添加到數據類型:

data Checked a = forall b. Show b => Checked (Either (Warning, Maybe (Checked b), a) a) 

instance Show a => Show (Checked a) where 
    show (Checked (Right v)) = show v 
    show (Checked (Left (w, Nothing, v))) = show w ++ show v 
    show (Checked (Left (w, Just ch, v))) = show w ++ show v ++ "caused by" ++ show ch 
+0

謝謝Sjoerd,但有沒有一種解決方案,我不必污染以這種方式檢查顯示?因爲現在編譯器要求在其他Checked實例聲明中顯示a =>約束,例如與您無關的應用程序Show –

+1

@RobertOnslow您可以在沒有存在量化的情況下管理嗎? '數據檢查b = ...'會這樣嗎?如果可以的話,你可以在沒有顯示上下文的情況下工作。或者,將整個事情包裝在GADT中解決你所有的麻煩? – AndrewC

+0

@AndrewC我會仔細考慮先檢查b。謝謝。 –

3

添加Show約束的數據類型定義。

data Checked a = forall b. Show b => Checked (Either (Warning, Maybe (Checked b), a) a) 

您還可以使用各種約束作爲

{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE ConstraintKinds #-} 
{-# LANGUAGE ExistentialQuantification #-} 

data Checked a c = forall b. c b => Checked (Either (Maybe (Checked b c), a) a) 

instance (Show a) => Show (Checked a Show) where 
show (Checked (Right v)) = show v 
show (Checked (Left (Nothing, v))) = show v 
show (Checked (Left (Just ch, v))) = show v ++ "caused by" ++ show ch