Wenn Sie nur die offensichtliche Einschränkung angeben - und einige notwendige Sprachpragmas hinzufügen -, funktioniert alles einwandfrei. Damit Foobar
zur Anzeige gebracht werden kann, muss das Feld Foo
darstellbar sein, so dass wir eine Show (x (Foobar x))
Einschränkung benötigen. Und wenn wir danach fragen, alles funktioniert nur aus:
{-# LANGUAGE FlexibleContexts, UndecidableInstances, StandaloneDeriving #-}
data Foobar x = Foo (x (Foobar x))
deriving instance Show (x (Foobar x)) => Show (Foobar x)
Dann:
λ> 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")])])
Ich bin ein wenig überrascht, dies funktioniert, aber nicht übermäßig :-)
das ist übrigens genau das, was GHC von euch fragt, ob Sie versuchen, Show
für Foobar
abzuleiten:
λ> 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))
Alles, was wir tun mussten, war StandaloneDeriving
und genau diese Einschränkung angeben!
, auch klar zu sein, der StandaloneDeriving
Teil ist optional - es jede Magie nicht tut, und die Instanz ist nicht allzu schwer von Hand zu schreiben:
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
Das ist [wie 'Show' definiert ist für' Fix'] (https://hackage.haskell.org/package/recursion-schemes-4.1.2/docs/src/Data-Functor -Foldable.html # Fix) in Rekursionschemata. – Cirdec
Ah ja, das macht Sinn - denn das * ist * 'Fix', bis zum Umbenennen! Das hätte ich sofort bemerken müssen :-) –
Ich war mir sicher, dass dieser Typ schon irgendwo in den Bibliotheken war, aber ich konnte ihn aus irgendeinem Grund nicht sehen ... – MathematicalOrchid