<div class="gmail_quote">On Thu, Jul 2, 2009 at 8:32 PM, Magicloud Magiclouds <span dir="ltr">&lt;<a href="mailto:magicloud.magiclouds@gmail.com">magicloud.magiclouds@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Wow, this complex.... Thank you. I will try that.</blockquote><div><br></div><div>No, don&#39;t! &nbsp;There is an easier way.</div><div><br></div><div>Don&#39;t use a class, just use a record.</div><div><br></div><div>I would translate your class as:</div>
<div><br></div><div>data Widget = Widget {</div><div>&nbsp;&nbsp; &nbsp;widgetRun :: IO ()</div><div>}</div><div><br></div><div>If you need more capabilities, add them as fields in this record. &nbsp;There is no need for typeclasses here.</div>
<div><br></div><div>Keep in mind that with this solution *and* with the ExistentialQuantification solution, there is no possibility of downcasting. &nbsp;I.e. if you were planning on making a GraphicalWidget subclass, and them somewhere seeing if a a Widget is actually a GraphicalWidget, you will be disappointed. &nbsp;The solution in this case is to redesign your software not to need downcasting. &nbsp;This is the point at which you are forced to move away from OO thinking.</div>
<div><br></div><div>Luke</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<div><div></div><div class="h5"><br>
On Fri, Jul 3, 2009 at 12:24 PM, Ross Mellgren&lt;<a href="mailto:rmm-haskell@z.odi.ac">rmm-haskell@z.odi.ac</a>&gt; wrote:<br>
&gt; You have a couple problems here.<br>
&gt;<br>
&gt; The first is that GHC has no idea what particular type &#39;w&#39; widgetList has,<br>
&gt; because the empty list is polymorphic.<br>
&gt;<br>
&gt; The second is that it looks like you probably want a heterogeneous list of<br>
&gt; widgets -- that is, possibly different types of widget as long as they all<br>
&gt; conform to Widget. To do this you&#39;ll need ExistentialQuantification (or<br>
&gt; GADTs I guess?).<br>
&gt;<br>
&gt; For example:<br>
&gt;<br>
&gt; {-# LANGUAGE ExistentialQuantification #-}<br>
&gt;<br>
&gt; class Widget w where<br>
&gt; &nbsp; &nbsp;widgetRun :: w -&gt; IO ()<br>
&gt;<br>
&gt; data SomeWidget = forall w. Widget w =&gt; SomeWidget w<br>
&gt;<br>
&gt; widgetList :: [(Integer, Integer, SomeWidget)]<br>
&gt; widgetList = []<br>
&gt;<br>
&gt; main = mapM aux widgetList<br>
&gt; &nbsp; &nbsp;aux (x, y, sw) =<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;case sw of<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SomeWidget w -&gt; widgetRun w<br>
&gt;<br>
&gt; Note that the type variable for widgetList &#39;w&#39; has disappeared. Before, with<br>
&gt; the type variable &#39;w&#39;, all elements of the widgetList had to be of the same<br>
&gt; type (lists being homogeneous). By wrapping up the type variable &#39;w&#39; inside<br>
&gt; SomeWidget, you can now have whatever types of widgets in that SomeWidget,<br>
&gt; e.g.<br>
&gt;<br>
&gt; data Button = Button (IO ())<br>
&gt; instance Widget Button where widgetRun = ...<br>
&gt;<br>
&gt; data Label = Label (String -&gt; IO ())<br>
&gt; instance Widget Label where widgetRun = ...<br>
&gt;<br>
&gt; widgetList:: [(Integer, Integer, SomeWidget)]<br>
&gt; widgetList =<br>
&gt; &nbsp; &nbsp;[ SomeWidget (Button $ putStrLn &quot;ding!&quot;)<br>
&gt; &nbsp; &nbsp;, SomeWidget (Label $ putStrLn . (&quot;entered: &quot; ++)) ]<br>
&gt;<br>
&gt; Before, without existential quantification, you had to have all the same<br>
&gt; type of widget (e.g. all Button or all Label)<br>
&gt;<br>
&gt; Hope this makes it more clear.<br>
&gt;<br>
&gt; -Ross<br>
&gt;<br>
&gt; On Jul 3, 2009, at 12:00 AM, Magicloud Magiclouds wrote:<br>
&gt;<br>
&gt;&gt; Hi,<br>
&gt;&gt; &nbsp;I thought &quot;class&quot; was for this purpose. But it turns out not.<br>
&gt;&gt; &nbsp;Code as following could not compiled.<br>
&gt;&gt;<br>
&gt;&gt; 1 main = do<br>
&gt;&gt; 2 &nbsp; mapM_ (\(x, y, widget) -&gt; do<br>
&gt;&gt; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a &lt;- widgetRun widget<br>
&gt;&gt; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;putStrLn $ show a<br>
&gt;&gt; 5 &nbsp; &nbsp; &nbsp; &nbsp; ) widgetList<br>
&gt;&gt; 6<br>
&gt;&gt; 7 widgetList :: (Widget w) =&gt; [(Integer, Integer, w)]<br>
&gt;&gt; 8 widgetList = []<br>
&gt;&gt; 9<br>
&gt;&gt; 10 class Widget w where<br>
&gt;&gt; 11 &nbsp; widgetRun :: w -&gt; IO ()<br>
&gt;&gt; ---<br>
&gt;&gt; % ghc --make tmp/test.hs<br>
&gt;&gt; [1 of 1] Compiling Main &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( tmp/test.hs, /tmp/Main.o )<br>
&gt;&gt;<br>
&gt;&gt; tmp/test.hs:3:16:<br>
&gt;&gt; &nbsp; Ambiguous type variable `t&#39; in the constraint:<br>
&gt;&gt; &nbsp; &nbsp; `Widget t&#39; arising from a use of `widgetRun&#39; at tmp/test.hs:3:16-31<br>
&gt;&gt; &nbsp; Probable fix: add a type signature that fixes these type variable(s)<br>
&gt;&gt; --<br>
&gt;&gt; 竹密岂妨流水过<br>
&gt;&gt; 山高哪阻野云飞<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; Haskell-Cafe mailing list<br>
&gt;&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt;&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
--<br>
竹密岂妨流水过<br>
山高哪阻野云飞<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">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>