Hi Matthijs,<br><br>This is a shameless plug for EMGM, a library for generic programming that we&#39;ve been working on at Utrecht.<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">| However, there are two issues bothering me still. The first is that the<br>
| Core types (in particular CoreExpr) are not instances of Show. They are<br>
| instances of Outputable, which allows them to be pretty printed.<br>
| However, this pretty printing is good to view the structure of the<br>
| expression that the CoreExpr represents, but doesn&#39;t show the structure<br>
| of the CoreExpr itself. For example, tuple construction is printed<br>
| simply as (a, b), while the actual core expression is a nested<br>
| application of two types, and a and b to the GHC.Tuple.(,) function<br>
| (or datacon?). Also, the exact constructors used are not quite clear,<br>
<br>
</div>There&#39;s absolutely no reason why<br>
 &nbsp; &nbsp; &nbsp; &nbsp;CoreExpr<br>
 &nbsp; &nbsp; &nbsp; &nbsp;CoreBind<br>
 &nbsp; &nbsp; &nbsp; &nbsp;Type<br>
should not be an instance of Show. &nbsp;It&#39;d take you 10 mins to make it so, with the aid of &#39;standalone deriving&#39; (described in the GHC user manual).<br>
<br>
There *is* a reason why TyCon and Class are not:<br>
 &nbsp; &nbsp; &nbsp; &nbsp;a TyCon<br>
 &nbsp; &nbsp; &nbsp; &nbsp;enumerates its DataCons<br>
 &nbsp; &nbsp; &nbsp; &nbsp;whose type mentions the TyCon<br>
<br>
In short, the data structures are, by design, cyclic. &nbsp;Printing one of these would take a long time.<br>
<br>
But I bet you could get a long way with the three above, plus just printing the *name* of a TyCon or Class or Id. &nbsp;Something like:<br>
 &nbsp; &nbsp; &nbsp; &nbsp;instance Show TyCon where<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; show tc = showSDoc (ppr tc)<br></blockquote></div><br>Suppose you want to print a type with the exception of one constructor, because it is mutually recursive with another or just prints out lots of useless information. There are at least two ways to do it, one with EMGM, and one with standalone deriving. I show both below.<br>
<br><span style="font-family: courier new,monospace;">&gt; {-# LANGUAGE TemplateHaskell #-}<br>&gt; {-# LANGUAGE FlexibleInstances #-}<br>&gt; {-# LANGUAGE FlexibleContexts #-}<br>&gt; {-# LANGUAGE MultiParamTypeClasses #-}<br>
&gt; {-# LANGUAGE OverlappingInstances #-}<br>&gt; {-# LANGUAGE UndecidableInstances #-}<br>&gt; {-# LANGUAGE StandaloneDeriving #-}<br>&gt; <br>&gt; module Example where<br>&gt; <br>&gt; import qualified Generics.EMGM as G<br>
&gt; <br>&gt; -----------------------------------------<br>&gt; <br>&gt; data A = A0 Int&nbsp; | A1 B<br>&gt; data B = B0 Char | B1 A<br>&gt; <br>&gt; $(G.derive &#39;&#39;A)<br>&gt; $(G.derive &#39;&#39;B)<br>&gt; <br>&gt; instance G.Rep G.Show B where<br>
&gt;&nbsp;&nbsp; rep = G.Show (\_ _ -&gt; f)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; where<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f (B0 c) = showString &quot;(B0 &quot; . showChar c . showString &quot;)&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f (B1 _) = showString &quot;(B1 &lt;some A&gt;)&quot;<br>&gt; <br>
&gt; valAB = A1 (B1 (A0 37))<br>&gt; showAB = G.show valAB<br>&gt; <br>&gt; -----------------------------------------<br>&gt; <br>&gt; data C = C0 Int&nbsp; | C1 D<br>&gt; data D = D0 Char | D1 C<br>&gt; <br>&gt; deriving instance Show C<br>
&gt; instance Show D where<br>&gt;&nbsp;&nbsp; showsPrec _ = f<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; where<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f (D0 c) = showString &quot;(D0 &quot; . showChar c . showString &quot;)&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f (D1 _) = showString &quot;(D1 &lt;some C&gt;)&quot;<br>
&gt; <br>&gt; valCD = C1 (D1 (C0 37))<br>&gt; showCD = show valCD<br>&gt; <br>&gt; -----------------------------------------</span><br>
<br>The first one uses EMGM&#39;s Template Haskell-based derive function to generate the type representation. I then give an overriding instance for the generic Show function (where G.Show is a newtype used for all show/shows/showsPrec generic functions). So, the constructor B1 will not print out the value of its A-type argument.<br>
<br>The second uses standalone deriving and a handwritten instance for D that does the same thing as the first solution did for B.<br><br>What&#39;s the difference? Well, between these instances of G.Show and Show, there&#39;s not much. However, the EMGM approach gives you access to a lot of other generic functions including Read, Crush, Collect, etc. See the documentation for all of them [1].<br>
<br>One function you may be able to take advantage of is &#39;collect&#39;, perhaps to collect the B values in valAB.<br><br><span style="font-family: courier new,monospace;">*Example&gt; G.show (G.collect valAB :: [B])</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">&quot;[(B1 &lt;some A&gt;)]&quot;</span><br style="font-family: courier new,monospace;"><br>Moral of the story: you can do it either way, but EMGM gives you a lot extra.<br>
<br>Apologies for the self-promotion, but we&#39;re looking for people who might want to use EMGM. ;) If you have feedback, let us know! [2]<br><br>Regards,<br>Sean<br><br>[1] <a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/emgm">http://hackage.haskell.org/cgi-bin/hackage-scripts/package/emgm</a><br>
[2] <a href="http://www.cs.uu.nl/wiki/GenericProgramming/EMGM">http://www.cs.uu.nl/wiki/GenericProgramming/EMGM</a><br>