On Mon, Jan 12, 2009 at 5:56 PM, Stephen Hicks <span dir="ltr">&lt;<a href="mailto:sdh33@cornell.edu">sdh33@cornell.edu</a>&gt;</span> wrote:<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;">
-- This instance definition is broken...<br>
instance (Monad m,Pick (a,b) c) =&gt; Pick (m a,m b) (m c) where<br>
 &nbsp; &nbsp;pick (ma,mb) = do { a &lt;- ma; b &lt;- mb; return $ pick (a,b) }</blockquote><div><br>First, and I know these types of comments are generally unwanted, but I recommend you <i>not do this</i>.&nbsp; You are only making pain for yourself later.&nbsp; Haskell is not good at this type of ad-hoc polymorphism (partially because it does not play well with inference).&nbsp; I.e. whyever you think you need this machinery, I suggest you spend some time rethinking why this is really necessary.<br>
<br>Okay, now to explain this instance.<br><br>An instance Pick (a,b) c is just a function (a,b) -&gt; c.&nbsp; So this instance reduces to the possibility of writing a function:<br><br>monadify :: ((a,b) -&gt; c) -&gt; ((m a, m b) -&gt; m c)<br>
<br>Which is only implementable by executing both actions m a and m b (because you need both an a and a b to pass to c).&nbsp; Consider what would happen if a pick function looked at the contents of its argument?&nbsp; e.g. maybe someone writes:<br>
<br>instance Pick (Int,Int) Int where<br>&nbsp;&nbsp;&nbsp; pick (x,y) = min x y<br><br>Then you would have to know the actual values to decide what to return, thus both actions must be executed.<br><br>One thing I always like to do when I&#39;m writing typeclasses is write the proof term library first (i.e. explicit dictionary passing) and then start turning those into typeclasses.&nbsp; This practice helps to weed out impossible ideas (eg. if you can&#39;t do what you want by explicitly passing dictionaries, how is the compiler going to infer the dictionaries for you?), and also to make more transparent what terms are being constructed.<br>
<br>As an example, you might start:<br><br>type PickD a b = a -&gt; b<br><br>leftTuple :: PickD (a,b) a<br>leftTuple = fst<br>rightTuple :: PickD (a,b) b<br>rightTuple = snd<br> func :: PickD (a,b) c -&gt; PickD (d -&gt; a, d -&gt; b) (d -&gt; c)<br>
func p (f,g) x = p (f x, g x)<br><br>...<br><br>And do this for each of your proposed instances.&nbsp; Then do an example use case, using these functions explicitly, and try to envisage an algorithm which might pick the functions for you.&nbsp; Then it will be much more obvious if it is possible to typeclassify these, and if so, how.<br>
<br>Luke<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
<br>
foo :: Pick (String,Int) t =&gt; String -&gt; t<br>
foo = pick (id :: String -&gt; String, length :: String -&gt; Int)<br>
<br>
toStr :: String -&gt; IO String<br>
toStr s = putStrLn &quot;str&quot; &gt;&gt; return s<br>
toInt :: String -&gt; IO Int<br>
toInt s = putStrLn &quot;int&quot; &gt;&gt; return (length s)<br>
<br>
bar :: Pick (String,Int) t =&gt; String -&gt; IO t<br>
bar = pick (toStr,toInt)<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>
</blockquote></div><br>