<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Wordy (and yet technically accurate) names aside, isn't this basically the same thing, except that you must pass the dictionary around by hand?<div><br></div><div>What is the advantage of doing the dictionary passing manually, other than being able to avoid the scoping issue (that requires case) and the slightly odd syntax?</div><div><br></div><div>I'm not saying you're wrong or anything, I'm just curious on your opinion.</div><div><br></div><div>To expand your example, would you suggest something like:</div><div><br></div><div>data Widget = Widget { widgetRun :: IO () }</div><div><br></div><div>data Label = Label (String -&gt; IO ())</div><div>data Button = Button (IO ())</div><div><br></div><div>labelToWidget = Widget runLabel</div><div>buttonToWidget = Widget runButton</div><div><br></div><div>widgetList :: [(Integer, Integer, Widget)]</div><div>widgetList = [labelToWidget myLabel, buttonToWidget myButton]</div><div><br></div><div>?</div><div><br></div><div>Regarding downcasting, you'd have to use Data.Dynamic or Data.Typeable right?</div><div><br></div><div>-Ross</div><div><br></div><div><br></div><div><br><div><div>On Jul 3, 2009, at 3:08 AM, Luke Palmer wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><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't! &nbsp;There is an easier way.</div><div><br></div><div>Don'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 'w' 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'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 'w' has disappeared. Before, with<br> &gt; the type variable 'w', all elements of the widgetList had to be of the same<br> &gt; type (lists being homogeneous). By wrapping up the type variable 'w' 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 "ding!")<br> &gt; &nbsp; &nbsp;, SomeWidget (Label $ putStrLn . ("entered: " ++)) ]<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 "class" 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' in the constraint:<br> &gt;&gt; &nbsp; &nbsp; `Widget t' arising from a use of `widgetRun' 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></blockquote></div><br></div></body></html>