Reputation: 32449
I started with haskell yesterday and am still completely lost on the shore of this brave new world. Now I have run into the following issue:
Let's assume I have some function that does some magic to an integer and another variable:
makeTuple :: Int -> a -> (Int, a)
makeTuple n x = (n, x)
Now I want to apply this function to all elements of a list. So far no problem, as mapping is your daily bread and butter in python (where I come from), too.
makeTupleList :: Int -> [a] -> [ (Int, a) ]
makeTupleList n x = map (makeTuple n) x
As far as I understand, the binary function makeTuple is applied partially with the integer n and hence becomes a unary function which can be mapped to each element of x. So far, all is well.
But what do I do when the makeTuple function has another signature, like:
makeTuple2 :: a -> Int -> (Int, a)
makeTuple2 x n = (n, x)
Many ways lead to Rome: the effect is the same, but the way is another. Now obviously the mapping doesn't work anymore: The function expects an Int and gets an a.
makeTupleList2 :: Int -> [a] -> [ (Int, a) ]
makeTupleList2 n x = map (makeTuple2 n) x -- boolshit
This was to be expected. My -maybe too pythonic- workaround is using another function to pass the parameters where they should go:
makeTupleList2 :: Int -> [a] -> [ (Int, a) ]
makeTupleList2 n x = map (\x -> makeTuple2 x n) x
Question: What is the preferred functional, haskell-style way of partially applying functions when the parially applied parameters isn't the leftmost?
Upvotes: 13
Views: 2809
Reputation: 139890
You can use flip
, which swaps the first and second arguments of a function.
makeTupleList2 n x = map (flip makeTuple2 n) x
Another option is to use the backticks syntax to make an infix operator and then partially apply that using an operator section.
maleTupleList2 n x = map (`makeTuple2` n) x
Or, as you said we can use a lambda expression. Which one to use depends on context and personal taste. Use whatever you feel is most clear.
PS: What you're doing is called partial application. Currying is the process of transforming a function taking multiple arguments (a, b) -> c
into curried form a -> b -> c
so that it can be partially applied.
Upvotes: 16
Reputation: 25654
If your functions are only tuple constructors:
makeTuple x y = (x,y)
(which can also be written as makeTuple = (,)
) then there is a special extension for this:
{-# LANGUAGE TupleSections #-}
makeTupleList2 n x = map (n,) x
makeTupleList2' n x = map (,n) x -- Use n as the second component
which can also be written as
makeTupleList2 n = map (n,)
makeTupleList2' n = map (,n)
Otherwise use ways already suggested.
Upvotes: 1
Reputation: 13032
You can replace \x -> makeTuple2 x n
with flip makeTuple2 n
, because the Prelude defines flip
like: (my implementation, not theirs)
flip :: (a -> b -> c) -> b -> a -> c
flip f y x = f x y
Hence we get
makeTupleList2' = map . flip makeTuple2
Or, seeing as how its just a tuple:
makeTupleList2'' = map . (,)
Also note (I'm not sure how efficient this is), you could use zip:
makeTupleList2''' :: a -> [b] -> [(a, b)]
makeTupleList2''' = zip . repeat
Upvotes: 1
Reputation: 2392
In this particular case you could use flip makeTuple2 n
, but that only works for functions with two arguments. But generally, I don't find your solution with the lambda un-haskelly or too pythonic.
Upvotes: 1