2012-10-24 63 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