2

I'm trying to apply a tuple of functions to a tuple of values

λ> let foo = ((+1), (*3), ((:)5))  #Each function has type: a -> a

λ> let bar  = (1, 5, [0])          #Each value of the corresponding tuple has type a

How do I implement:

toImplement foo bar = ?

such that:

λ> toImplement foo bar
-> (2, 15, [0,5]) # using foo and bar above

How can you implement this in general for any valid foo and bar (of the same length)?

[I looked at this problem, but it is implemented for a fixed type. I require a general implementation]

Motivation:

I'm trying to write folds efficiently.

let acc1 = \x acc -> x*x:acc
let acc2 = (+)
foldr (\x acc -> (acc1 x (fst acc), acc2 x ( snd acc))) ([],0) [1..10]
> ([1,4,9,16,25,36,49,64,81,100],55)

I have 2 different accumulators acc1 & acc2 that loop over the list exactly once. I'd like to do this for arbitrary number of accumulators all of whom have type a -> b [where a is the type of the elements in the list and b is of the type of the output of the accumulator] It looks clumsy, having to access the tuples using fst and snd :/

Community
  • 1
  • 1
GeneralBecos
  • 2,476
  • 2
  • 22
  • 32
  • 3
    "How can you implement this in general for any valid foo and bar (of the same length)?" --- you cannot make it generic for tuples. – zerkms Mar 30 '15 at 20:11
  • 2
    You can't write a single `toImplement` that would work with tuples of arbitrary size. Sure, there are probably some really hackish ways to get it to work using advanced language features and a bunch of extensions, but it's probably more trouble than it's worth to copy/paste essentially the same definition several times to get `toImplement`, `toImplement3` .. `toImplementN`. – bheklilr Mar 30 '15 at 20:12
  • Is there any zen behind why Haskell does not allow working with arbitrary tuples? – GeneralBecos Mar 30 '15 at 20:32
  • 2
    It wouldn't work not because Haskell lists require that all elements of the list be the same and the list can be of any length (infinity is not frowned upon), but Haskell tuples allow for any type to be in them but they have to be fixed size. So your problem is basically looking for a sweet spot between those two restrictions but it would be practically impossible to find one. Python would let you do this, but not Haskell – smac89 Mar 30 '15 at 20:49
  • 2
    For your fold use case, you can make it a bit nicer by deconstructing the tuple with pattern matching in the lambda: `(\x (a, b) -> ...)`. For an even shorter solution, you could use `(***)` from `Control.Arrow`: `foldr (\x -> acc1 x *** acc2 x) ([],0) [1..10]`. You could even eliminate all the lambdas with `Applicative` (although I'd suggest the other, simpler `(***)`-based solution): `foldr ((***) <$> acc1 <*> acc2) ([],0) [1..10]`. – David Young Mar 30 '15 at 20:59
  • @DavidYoung: I'm going to take a couple of days to wrap my head around that. Sweet! :) – GeneralBecos Mar 30 '15 at 21:10

1 Answers1

6

As mentioned in the comments, haskell does not allow one to implement generic functions for tuples of arbitrary size. Hence you need to implement a particular function for every size separately.

Eg:

toImplement3 :: (b0 -> c0, b1 -> c1, b2 -> c2) -> (b0, b1, b2) -> (c0, c1, c2)
toImplement3 (f1, f2, f3) (a1, a2, a3) = (f1 a1, f2 a2, f3 a3)
zerkms
  • 249,484
  • 69
  • 436
  • 539