15

In Python and Ruby (and others as well, I'm sure). you can prefix an enumerable with * ("splat") to use it as an argument list. For instance, in Python:

>>> def foo(a,b): return a + b
>>> foo(1,2)
3
>>> tup = (1,2)
>>> foo(*tup)
3

Is there something similar in Haskell? I assume it wouldn't work on lists due to their arbitrary length, but I feel that with tuples it ought to work. Here's an example of what I'd like:

ghci> let f a b = a + b
ghci> :t f
f :: Num a => a -> a -> a
ghci> f 1 2
3
ghci> let tuple = (1,2)

I'm looking for an operator (or function) that allows me to do:

ghci> f `op` tuple
3

I have seen (<*>) being called "splat", but it doesn't seem to be referring to the same thing as splat in other languages. I tried it anyway:

ghci> import Control.Applicative
ghci> f <*> tuple

<interactive>:1:7:
    Couldn't match expected type `b0 -> b0'
                with actual type `(Integer, Integer)'
    In the second argument of `(<*>)', namely `tuple'
    In the expression: f <*> tuple
    In an equation for `it': it = f <*> tuple
duplode
  • 33,731
  • 7
  • 79
  • 150
gfxmonk
  • 8,614
  • 5
  • 42
  • 53

3 Answers3

16

Yes, you can apply functions to tuples, using the tuple package. Check out, in particular, the uncurryN function, which handles up to 32-tuples:

Prelude Data.Tuple.Curry> (+) `uncurryN` (1, 2)
3
ovolve
  • 9,191
  • 3
  • 16
  • 13
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • I'm guessing this uses Template Haskell? – Chuck Aug 14 '11 at 02:42
  • Thanks, this works a treat. Unfortunate that it looks to arbitrarily be defined only up to tuples of 15 elements, but that's probably plenty ;) – gfxmonk Aug 14 '11 at 04:04
  • Yeah, it has to be defined for individual tuple types because in Haskell, each tuple type is technically a different type. (So `(a, b)`, or "pair", is a completely unrelated type to `(a, b, c)`, or "triple" -- they just have a special syntax that allows the construction of arbitrarily-large such types.) I don't think the above package is using Template Haskell, though I don't recognise the "|" symbol used in the class definition. – mgiuca Aug 14 '11 at 04:14
  • 2
    @mgiuca: The "|"-symbol in this context denotes a [Functional Dependency](http://www.haskell.org/haskellwiki/Functional_dependencies). – shang Aug 14 '11 at 04:25
  • @Chuck: There is no Template Haskell in the tuple package (though there is some custom Haskell code which emits other Haskell code as a String). – Daniel Wagner Aug 14 '11 at 06:53
3

The uncurry function turns a function on two arguments into a function on a tuple. Lists would not work in general because of their requirement for homogeneity.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • Just to be clear: are you saying it can't be done on arbitrary-length tuples, but uncurry works for the special case of a pair? – gfxmonk Aug 14 '11 at 01:41
  • @gfxmonk: Yes. Each combination of number and combination of types in a tuple is a distinct type in Haskell's type system, so a function can't take every tuple type. – Chuck Aug 14 '11 at 02:28
3

No, Haskell's type system doesn't like that. Check this similar question for more details:

How do I define Lisp’s apply in Haskell?

BTW, the splat operator you talk about is also known as the apply function, commonly found on dynamical functional languages (like LISP and Javascript).

Community
  • 1
  • 1
hugomg
  • 68,213
  • 24
  • 160
  • 246
  • 1
    I believe this is correct for lists, but I asked specifically about tuples in the question. – gfxmonk Aug 14 '11 at 05:34
  • @gfxmonk: Still, enumerables in Python are moe akin to lists, IMO, since they can be of arbritrary length and the splat works the same. In Haskell you can't have a function work on arbritrary tuples unless you use deep magic. – hugomg Aug 14 '11 at 14:38