I would like to be able to combine two tuples of the same length using a function, similar to the zipWith function from base.
For example, for the case of length 3 tuples:
zipTupleWith f (a0,a1,a2) (b0,b1,b2) = (f a0 b0, f a1 b1, f a2 b2)
Though I would like a single function that works for any length.
I have made a function zipTupleWith using the lens package:
zipTupleWith :: (Each s1 t1 a a, Each s2 s2 b b) => (a -> b -> a) -> s1 -> s2 -> t1
zipTupleWith f a b = a & partsOf each %~ flip (zipWith f) (b ^.. each)
This can zipWith two tuples so long as the function is of type a -> b -> a. This restriction is because of the partsOf function being used on the argument a.
There are 3 reasons that I'm not happy with my solution:
- I would like to be able to use a function of type
a -> b -> c, allowing things likezipTuple = zipTupleWith (,). - The above implementation will not catch errors caused by tuples of different lengths being passed in (
zipTupleWith (+) (1,2,3) (100,100) = (101, 102, 3)- I would like this to be a compilation error). - It creates an intermediary list (
b ^.. each).
So, is there a way of doing this using optics?
I saw that the tuple-th package can do this, but I would prefer to avoid adding another dependency just for this, and Template Haskell seems excessive for what I'm doing.