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.
Vector
, which supports zips of arbitrary arity via itsApplicative
instance (and fixed small arity via the usualzipWith
,zipWith3
, etc. names)? – Instructivevector-sized
"this approach requires us to carry a runtime representation of length, which is a significant memory overhead for small vectors.". My tuples are small. – OrrinEach
) is going to struggle to avoid your problems 2 and 3. But you can really easily make a type class solution, and if your tuples are small then you don't need many instances so the boilerplate isn't too bad. – SenescentVector
s do not carry a runtime representation of their length (or at least not any extra such representation compared to the efficient underlyingvector
package'sVector
s). – Instructivevector
package'sVector
contains. – Orrin