Actually, after thinking it back, I found out one other method. The key idea is to split what is common to every shape with what is not:<br><br><span style="font-family: courier new,monospace;">data Circle = Circle { cr :: Double }<br>

data Rectangle = Rectangle { rw, rh :: Double }<br><br>class Shapeful s where<br>    name :: s -&gt; String<br>    fields :: s -&gt; String<br><br>instance Shapeful Circle where<br>    name _ = &quot;Circle&quot;<br>    fields (Circle cr) = show cr<br>

<br>instance Shapeful Rectangle where<br>    name _ = &quot;Rectangle&quot;<br>    fields (Rectangle rw rh) = show rw ++ &quot;, &quot; ++ show rh<br><br>data Shape = forall s. (Shapeful s)<br>          =&gt; Shape { sx, sy :: Double,<br>

                     inner  :: a }<br><br>drawShape :: Shape -&gt; String<br>drawShape (Shape sx sy inner) = name inner ++ &quot; (&quot; ++ show sx ++ &quot;, &quot; ++<br>                                show sy ++ &quot;, &quot; ++ fields inner ++ &quot;)&quot;<br>

</span><br><br><font face="courier new,monospace">list :: [Shape]<br>list = [Shape 10 10 $ Circle 5, Shape 40 40 $ Rectangle 12 10]<br><br><br></font>Since you loose the exact type of what contains Shape, your class &quot;Shapeful&quot; must provide all the necessary information (but that is kind of usual in Haskell).<br>

The advantage here is that you generalize the position (sx and sy fields) which are no longer duplicated within Rectange and Circle.<br><br><br>2011/3/29 Yves Parès <span dir="ltr">&lt;<a href="mailto:limestrael@gmail.com">limestrael@gmail.com</a>&gt;</span><br>

<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Actually, Tako:<br><br><div><div><font face="&#39;courier new&#39;, monospace"><div class="im">

   data Shape = forall a. Drawable a =&gt; Shape a<br><br></div>Can also be done with GADTs:<br><br><font face="courier new,monospace">   data Shape where<br>
       Shape :: Drawable a =&gt; a -&gt; Shape<br></font></font></div></div><br>If wouldn&#39;t know if one approach is preferable to the other or if is just a matter of taste.<br><br>Your problem, Tad, is kind of common. I ran against it several times. I know of two ways to solve it :<br>


<br>- &quot;The open way&quot; (this is your method, with a class ShapeC and datatype ShapeD which wraps instances of ShapeC)<br><br>- &quot;The closed way&quot;, which can be broken in two alternatives:<br><br>* Using a plain Haskell98 ADT:<br>


<font face="courier new,monospace">    data Shape = Circle .... | Rectangle ....<br>    draw :: Shape -&gt; String<br>    draw (Circle ...) = ...<br>    draw (Rectangle ...) = ...<br><br><font face="arial,helvetica,sans-serif">Flexible and simple, but not safe, since you have no way to type-diferenciate Circles from Rectangles.<br>


<br>* Using a GADT and empty data declarations:<br><font face="courier new,monospace">    data Circle<br>    data Rectangle<br>    data Shape a where<br>        Circle :: Double -&gt; Double -&gt; Double -&gt; Shape Circle<br>


        Rectangle :: Double -&gt; Double -&gt; Double -&gt; Double -&gt; Shape Rectangle<br><br><font face="arial,helvetica,sans-serif">And then you can both use &quot;Shape a&quot; or &quot;Shape Circle/Shape Rectangle&quot;, which enables you either to make lists of Shapes or to specifically use Circles or Rectangles.<br>


<br>The drawback of it is that since you have a closed type (the GADT Shape), you cannot add a new shape without altering it.<br></font></font><br></font></font><div><div></div><div class="h5"><br><div class="gmail_quote">

2011/3/29 Steffen Schuldenzucker <span dir="ltr">&lt;<a href="mailto:sschuldenzucker@uni-bonn.de" target="_blank">sschuldenzucker@uni-bonn.de</a>&gt;</span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Tad,<br>
<br>
It doesn&#39;t look bad, but depending on what you want to do with the<br>
[ShapeD] aftewards you might not need this level of generality.<br>
<br>
Remember that the content of a ShapeD has type (forall a. ShapeC a =&gt;<br>
a), so all you can do with it is call class methods from ShapeC. So if<br>
all you do is construct some ShapeD and pass that around, the following<br>
solution is equivalent:<br>
<br>
data Shape = Shape {<br>
     draw :: String<br>
     copyTo :: Double -&gt;  Double -&gt; Shape<br>
     -- ^ We loose some information here. The original method of ShapeC<br>
     -- stated that copyTo of a Rectangle will be a rectangle again<br>
     -- etc. Feel free to add a proxy type parameter to Shape if this<br>
     -- information is necessary.<br>
}<br>
<br>
circle :: Double -&gt; Double -&gt; Double -&gt; Shape<br>
circle x y r = Shape dc $ \x y -&gt; circle x y r<br>
  where dc = &quot;Circ (&quot; ++ show x ++ &quot;, &quot; ++ show y ++ &quot;) -- &quot;&quot; ++ show r<br>
<br>
rectangle :: Double -&gt; Double -&gt; Double -&gt; Double -&gt; Shape<br>
rectangle x y w h = ... (analogous)<br>
<br>
shapes = [rectangle 1 2 3 4, circle 4 3 2, circle 1 1 1]<br><font color="#888888">
<br>
-- Steffen</font><div><div></div><div><br>
<br>
On 03/29/2011 07:49 AM, Tad Doxsee wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I&#39;ve been trying to learn Haskell for a while now, and recently<br>
wanted to do something that&#39;s very common in the object oriented<br>
world, subtype polymorphism with a heterogeneous collection. It took<br>
me a while, but I found a solution that meets my needs. It&#39;s a<br>
combination of solutions that I saw on the web, but I&#39;ve never seen<br>
it presented in a way that combines both in a short note. (I&#39;m sure<br>
it&#39;s out there somewhere, but it&#39;s off the beaten path that I&#39;ve been<br>
struggling along.)  The related solutions are<br>
<br>
1. section 3.6 of <a href="http://homepages.cwi.nl/%7Eralf/OOHaskell/paper.pdf" target="_blank">http://homepages.cwi.nl/~ralf/OOHaskell/paper.pdf</a><br>
<br>
2. The GADT comment at the end of section 4 of<br>
<a href="http://www.haskell.org/haskellwiki/Heterogenous_collections" target="_blank">http://www.haskell.org/haskellwiki/Heterogenous_collections</a><br>
<br>
I&#39;m looking for comments on the practicality of the solution, and<br>
references to better explanations of, extensions to, or simpler<br>
alternatives for what I&#39;m trying to achieve.<br>
<br>
Using the standard example, here&#39;s the code:<br>
<br>
<br>
data Rectangle = Rectangle { rx, ry, rw, rh :: Double } deriving (Eq,<br>
Show)<br>
<br>
drawRect :: Rectangle -&gt;  String drawRect r = &quot;Rect (&quot; ++ show (rx r)<br>
++ &quot;, &quot;  ++ show (ry r) ++ &quot;) -- &quot; ++ show (rw r) ++ &quot; x &quot; ++ show<br>
(rh r)<br>
<br>
<br>
data Circle = Circle {cx, cy, cr :: Double} deriving (Eq, Show)<br>
<br>
drawCirc :: Circle -&gt;  String drawCirc c = &quot;Circ (&quot; ++ show (cx c) ++<br>
&quot;, &quot; ++ show (cy c)++ &quot;) -- &quot; ++ show (cr c)<br>
<br>
r1 = Rectangle 0 0 3 2 r2 = Rectangle 1 1 4 5 c1 = Circle 0 0 5 c2 =<br>
Circle 2 0 7<br>
<br>
<br>
rs = [r1, r2] cs = [c1, c2]<br>
<br>
rDrawing = map drawRect rs cDrawing = map drawCirc cs<br>
<br>
-- shapes = rs ++ cs<br>
<br>
Of course, the last line won&#39;t compile because the standard Haskell<br>
list may contain only homogeneous types.  What I wanted to do is<br>
create a list of circles and rectangles, put them in a list, and draw<br>
them.  It was easy for me to find on the web and in books how to do<br>
that if I controlled all of the code. What wasn&#39;t immediately obvious<br>
to me was how to do that in a library that could be extended by<br>
others.  The references noted previously suggest this solution:<br>
<br>
<br>
class ShapeC s where draw :: s -&gt;  String copyTo :: s -&gt;  Double -&gt;<br>
Double -&gt;  s<br>
<br>
-- needs {-# LANGUAGE GADTs #-} data ShapeD  where ShapeD :: ShapeC s<br>
=&gt;  s -&gt;  ShapeD<br>
<br>
instance ShapeC ShapeD where draw (ShapeD s) = draw s copyTo (ShapeD<br>
s) x y = ShapeD (copyTo s x y)<br>
<br>
mkShape :: ShapeC s =&gt;  s -&gt;  ShapeD mkShape s = ShapeD s<br>
<br>
<br>
<br>
instance ShapeC Rectangle where draw = drawRect copyTo (Rectangle _ _<br>
rw rh) x y = Rectangle x y rw rh<br>
<br>
instance ShapeC Circle where draw = drawCirc copyTo (Circle _ _ r) x<br>
y = Circle x y r<br>
<br>
<br>
r1s = ShapeD r1 r2s = ShapeD r2 c1s = ShapeD c1 c2s = ShapeD c2<br>
<br>
shapes1 = [r1s, r2s, c1s, c2s] drawing1 = map draw shapes1<br>
<br>
shapes2 = map mkShape rs ++ map mkShape cs drawing2 = map draw<br>
shapes2<br>
<br>
-- copy the shapes to the origin then draw them shapes3 = map (\s -&gt;<br>
copyTo s 0 0) shapes2 drawing3 = map draw shapes3<br>
<br>
<br>
Another user could create a list of shapes that included triangles by<br>
creating a ShapeC instance for his triangle and using mkShape to add<br>
it to a list of ShapeDs.<br>
<br>
Is the above the standard method in Haskell for creating an<br>
extensible heterogeneous list of &quot;objects&quot; that share a common<br>
interface?  Are there better approaches?  (I ran into a possible<br>
limitation to this approach that I plan to ask about later if I can&#39;t<br>
figure it out myself.)<br>
<br>
- Tad<br>
<br>
_______________________________________________ Haskell-Cafe mailing<br>
list <a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote>
<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>
</div></div></blockquote></div><br>