Hi Tillmann,<br><br>That'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"><<a href="mailto:rendel@mathematik.uni-marburg.de">rendel@mathematik.uni-marburg.de</a>></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">
> f :: Int -> IO ()<br>
> f = undefined<br>
<br>
> g :: Int -> Int -> IO ()<br>
> g = undefined<br>
<br>
> h :: Int -> Int -> Int -> IO ()<br>
> h = undefined<br>
<br>
vtuple f :: IO (Int -> (Int, ()))<br>
vtuple g :: IO (Int -> Int -> (Int, (Int, ())))<br>
<br></div>
I've tried to type vtuple using a type class; [...]<div class="im"><br>
<br>
I've thought about it and it seems impossible to solve this problem<br>
-- you keep needing to ``split'' 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's argument. I tried it with type families,<br>
but I don'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 -> 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 -> b) = (a, F b)<br>
type instance G (a -> b) r = a -> G b r<br>
<br>
instance VTuple b => VTuple (a -> b) where<br>
vtuple = undefined<br>
<br>
A test case:<br>
<br>
f :: Int -> Bool -> Char -> Double -> IO ()<br>
f = undefined<br>
<br>
test = do<br>
vt <- vtuple f<br>
return (vt 5 True 'x' 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>