无法为此类型编写Show实例

时间:2016-05-10 20:49:42

标签: haskell typeclass

考虑以下类型声明:

deriving Show

现在为此编写一个Foobar x实例。我敢说你!

我随便写了x y,希望GHC做到这一点。但它抱怨它无法做到。 &#34;可怜的傻瓜&#34;,我想,并继续自己定义。但是......嗯...哦,实际上这很有意思......显然y仅在Show可展示SELECT (CAST(MAX(Id) AS DECIMAL(38,0)) + 1) AS 'New ID' FROM database WHERE Id NOT LIKE '%[^0-9]%' --filters out non-numeric ID values AND (LEN(Id) + 1) < 39 --ensures ID is less than length 39 ...或者......时显示。 ......那样的...... aaargh!

现在我确定我不可能成为第一个定义此类型的人。我不能成为第一个想要SELECT (CAST(MAX(CAST(Id AS DECIMAL(38,0))) AS DECIMAL(38,0)) + 1) AS 'New ID' FROM database WHERE Id NOT LIKE '%[^0-9]%' AND (LEN(Id) + 1) < 39 实例的人。所以有人必须弄清楚如何做到这一点。

3 个答案:

答案 0 :(得分:6)

如果您只是指定明显的约束 - 并添加一些必要的语言编译指示 - 一切正常。要使Foobar可显示,Foo的字段必须是可显示的,因此我们需要Show (x (Foobar x))约束。如果我们要求这样做,一切都会成功:

{-# LANGUAGE FlexibleContexts, UndecidableInstances, StandaloneDeriving #-}

data Foobar x = Foo (x (Foobar x))
deriving instance Show (x (Foobar x)) => Show (Foobar x)

然后:

λ> print $ Foo [Foo [], Foo [Foo []]]
Foo [Foo [],Foo [Foo []]]
λ> data SL a = S String | L [a] deriving Show
λ> print $ Foo (L [Foo (S "a"), Foo (L [Foo (S "b"), Foo (L []), Foo (S "c")])])
Foo (L [Foo (S "a"),Foo (L [Foo (S "b"),Foo (L []),Foo (S "c")])])

我对这项工作有点惊讶,但并不过分: - )

顺便提一下,如果您尝试为Show派生Foobar,这正是GHC所要求的:

λ> data Foobar x = Foo (x (Foobar x)) deriving Show

<interactive>:2:45:
    No instance for (Show (x (Foobar x)))
      arising from the first field of ‘Foo’ (type ‘x (Foobar x)’)
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Show (Foobar x))

我们所要做的只是使用StandaloneDeriving并准确指定约束!

另外,要明确的是,StandaloneDeriving部分是可选的 - 它没有做任何魔术,并且实例并不难以手工编写:

instance Show (x (Foobar x)) => Show (Foobar x) where
  showsPrec p (Foo x) = showParen (p > app_prec) $
                          showString "Foo " . showsPrec (app_prec + 1) x
    where app_prec = 10 :: Int

答案 1 :(得分:6)

以下是没有扩展的方法:

data Foobar x = Foo (x (Foobar x))

class Show1 f where
    showsPrec1 :: Show a => Int -> f a -> ShowS

instance Show1 f => Show (Foobar f) where
    showsPrec n (Foo v) = ("Foo " ++) . showsPrec1 n v -- doesn't handle n correctly because that's not the point of the question and would only distract from the actual important idea

Show1类(以及标准类型的一些实例)也可用on Hackage。定义它的模块使用了一些扩展 - 但只是为了减少样板,而不是为了使旧的Haskell2010无法做任何事情。

答案 2 :(得分:1)

好的,所以在玩代码时,我找到了一种的方法:

$csv->say ($out, [@pairs, @result]);

但是有一些问题。

  • 它没有产生完全正确的输出。 (缺少instance (Functor f, Show (f String)) => Show (Foobar f) where show = fold show fold :: Functor f => (f x -> x) -> Foobar f -> x fold f (Foo x) = f (fmap (fold f) x) 构造函数,并且引用了子表达式。)
  • 显然需要Foo才能工作。 (!)
  • 我尝试更改UndecidableInstances以包含show构造函数,但GHC恐慌(!!!)

我不知道你只是通过编写用户代码来实际崩溃GHC ......显然你可以做到。

Foo

我猜它被称为&#34;不可判断&#34;因为某种原因! O_O