Again, I think what you propose is different from what was asked.
On 2003-11-18 at 10:46EST "Abraham Egnor" wrote:
The classic way to write a lift function for tuples is, of course:
liftTup f (a, b) = (f a, f b)
which has a type of (a -> b) -> (a, a) -> (b, b). I've been wondering if it would be possible to write a function that doesn't require the types in the tuple to be the same, just that the types in the second tuple are the result of applying the type transformation implied in the function to be lifted to the types in the first tuple.
On Wed, Nov 19, 2003 at 05:25:19PM -0800, oleg@pobox.com wrote:
*Main> :t liftp forall a2 a a3 a1. (Typeable a, Typeable a1, Typeable a2, Typeable a3) => (Dynamic -> Dynamic) -> (a1, a3) -> (a, a2)
Here there is no visible relation between the types in the first tuple and the types in the second tuple. The ``type transformation implied in the function to be lifted'' is not reflected in the type of liftp. I think an example of what Abraham Egnor asked for is:
f1 :: a -> Maybe a f1 x = Just x
with desired type (Maybe Int, Maybe Bool) for the expression liftTup f1 (1, True). Yet another example is
data T a = T (a, a -> T a)
f2 :: T a -> T a f2 (T (repr, m)) = m repr
with desired type (T a, T b) -> (T a, T b) for liftTup f2, so that one can for example have
o1 :: Int -> T Int o1 x = T (x, \ x -> o1 (x * 2))
o2 :: Float -> T Float o2 x = T (x, \ x -> o2 (x * 2.0))
v = liftTup f2 (o1 1, o2 1.0)
One could expect v to have type (T Int, T Float), but I don't think the type system of Haskell can handle these simple, uncontrived examples. I don't intend this as a criticism, merely a fact. Of course, one can always defeat the static type system when it gets in the way, using Dynamics, as you demonstrated. -- Sebastien