Discussion:
[Haskell-cafe] apply function arguments in a list
(too old to reply)
Michael Mossey
2009-10-05 14:34:55 UTC
Permalink
If I have a list containing the arguments I want to give to a function, is
there a general way to supply those arguments in a compact syntax?

In other words, I could have

args = [1,2,3]
f x y z = ...

I would write

t = f (args!!0) (args!!1) (args!!2)

but there may be a neater, more general syntax. I tried writing a fold with
$, but I don't think that works because the type of each step is different.
I.e.

f :: a -> a -> a -> a
f x :: a -> a -> a
f x y :: a -> a
f x y z :: a

This would seem to preclude a general way of writing a function that
supplies arguments from a list.
Miguel Mitrofanov
2009-10-05 14:40:33 UTC
Permalink
t = let [x,y,z] = args in f x y z
Post by Michael Mossey
t = f (args!!0) (args!!1) (args!!2)
Neil Brown
2009-10-05 14:44:09 UTC
Permalink
Post by Michael Mossey
If I have a list containing the arguments I want to give to a
function, is there a general way to supply those arguments in a
compact syntax?
In other words, I could have
args = [1,2,3]
f x y z = ...
I would write
t = f (args!!0) (args!!1) (args!!2)
but there may be a neater, more general syntax.
In general, the problem is that you can't guarantee ahead of time that
the list will have three elements, so however you write it, you'll turn
a compile-time error (wrong number of args to function) into a run-time
error (!! says index is invalid). The neatest way is probably:

t [x,y,z] = f x y z

Which will give a slightly better error if the list is the wrong size.
If your function takes many arguments of the same type, perhaps you
could generalise it to take a list of arbitrary size, and do away with
requiring three arguments? Alternatively, use tuples if you want an
easy way to carry the arguments around together:

args = (1, 2, 3)
f x y z = ...

uncurry3 f (x,y,z) = f x y z

t = uncurry3 f

(uncurry already exists, I think uncurry3 is one you have to add yourself).

Neil.
gene
2009-10-05 20:58:40 UTC
Permalink
Post by Michael Mossey
If I have a list containing the arguments I want to give to a function, is
there a general way to supply those arguments in a compact syntax?
In general if you want to have a list contain the arguments to a
function that has arity 3 then use a list of triples.
So say you have a list with arguments that all numeric and you want
something that takes [(a,b,c)] and you want to say multiply a and b
together and then add c to that result you could write a lambda
function, and map it over the tuples in your list:

first if you already have a function that takes three individual
arguments, as someone was saying here is
the definition for converting a function from taking three separate
arguments and doing an uncurrying of a tupel fo three elements or
uncurry3:
definition:
uncurry3 f (a,b,c) = f a b c

type signature:
uncurry3
:: forall t t1 t2 t3. (t -> t1 -> t2 -> t3) -> (t, t1, t2) -> t3

Okay here is an example of doing an unnamed function, or lambda that
is mapped across a list of
triples as was described in my first sentence...:
map (\(a,b,c) -> a * b + c) [(2,4,9),(3,6,2)]
[17,20]

Using a list of tuples, because they can have differing types, you are
not locked to say all numerics:
map (\(a,b,c) -> c ++ "'s commission is " ++ show (a * b))
[(0.15,25.45,"Jim"),(0.08,18.95,"Ted")]
["Jim's commission is 3.8175","Ted's commission is 1.516"]

Not sure this is what you were even shooting for, but hopefully of
some use with some other project some day.

cheers to you,
gene

Continue reading on narkive:
Loading...