Hi Tillmann,<br><br>That&#39;s worked a treat -- thanks ever so much :)<br><br>Will<br><br><div class="gmail_quote">On Wed, Aug 11, 2010 at 7:50 PM, Tillmann Rendel <span dir="ltr">&lt;<a href="mailto:rendel@mathematik.uni-marburg.de">rendel@mathematik.uni-marburg.de</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Will Jones wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">
 &gt; f :: Int -&gt; IO ()<br>
 &gt; f = undefined<br>
<br>
 &gt; g :: Int -&gt; Int -&gt; IO ()<br>
 &gt; g = undefined<br>
<br>
 &gt; h :: Int -&gt; Int -&gt; Int -&gt; IO ()<br>
 &gt; h = undefined<br>
<br>
vtuple f :: IO (Int -&gt; (Int, ()))<br>
vtuple g :: IO (Int -&gt; Int -&gt; (Int, (Int, ())))<br>
<br></div>
I&#39;ve tried to type vtuple using a type class; [...]<div class="im"><br>
<br>
I&#39;ve thought about it and it seems impossible to solve this problem<br>
-- you keep needing to ``split&#39;&#39; the function type one arrow further on. <br>
</div></blockquote>
<br>
So you need to use recursion to handle the arbitrary deeply nested<br>
arrows in the type of vtuple&#39;s argument. I tried it with type families,<br>
but I don&#39;t see a reason why functional dependencies should not work.<br>
<br>
    {-# LANGUAGE FlexibleInstances, TypeFamilies #-}<br>
    module VTupleWithTypeFamilies where<br>
<br>
We use two type families to handle the two places where the result type<br>
of vtuple changes for different argument types.<br>
<br>
    type family F a<br>
    type family G a r<br>
<br>
So the intention is that the type of vtuple is as follows.<br>
<br>
    class VTuple a where<br>
      vtuple :: a -&gt; IO (G a (F a))<br>
<br>
The base case:<br>
<br>
    type instance F (IO ())   = ()<br>
    type instance G (IO ()) r = r<br>
<br>
    instance VTuple (IO ()) where<br>
      vtuple = undefined<br>
<br>
And the step case:<br>
<br>
    type instance F (a -&gt; b)   = (a, F b)<br>
    type instance G (a -&gt; b) r = a -&gt; G b r<br>
<br>
    instance VTuple b =&gt; VTuple (a -&gt; b) where<br>
      vtuple = undefined<br>
<br>
A test case:<br>
<br>
    f :: Int -&gt; Bool -&gt; Char -&gt; Double -&gt; IO ()<br>
    f = undefined<br>
<br>
    test = do<br>
      vt &lt;- vtuple f<br>
      return (vt 5 True &#39;x&#39; 1.3)<br>
<br>
Testing it with ghci yields the following type for test, which looks<br>
good to me.<br>
<br>
    test :: IO (Int, (Bool, (Char, (Double, ()))))<br>
<br>
HTH, Tillmann<br>
<br>
</blockquote></div><br>