Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bind the second argument in a function but not the first (in an elegant way)?

Is there a way in Haskell to bind the second argument but not the first of a function without using lambda functions or defining another "local" function?

Example. I have a binary function like:

sub :: Int -> Int -> Int sub x y = x - y  

Now if I want to bind the first argument, I can do so easily using (sub someExpression):

mapSubFrom5 x = map (sub 5) x  *Main> mapSubFrom5 [1,2,3,4,5] [4,3,2,1,0] 

That works fine if I want to bind the first n arguments without "gap".

If I want to bind the second argument but not the first, the two options I am aware of are more verbose:

Either via another, local, function:

mapSub5 x = map sub5 x     where sub5 x = sub x 5  *Main> mapSub5 [1,2,3,4,5] [-4,-3,-2,-1,0] 

Or using lambda:

mapSub5 x = map (\x -> sub x 5) x 

While both are working fine, I like the elegance of "sub 5" and wonder if there is a similarly elegant way to bind the n-th (n > 1) argument of a function?

like image 753
Frank Osterfeld Avatar asked Dec 29 '10 10:12

Frank Osterfeld


People also ask

How do you pass a second argument to a function?

function test (a,b) { // ... }; // pass only the second parameter test( ... , b); My current idea is to pass the second argument as a de facto dynamic default parameter as following: var defaultVar = "something"; function test (a, b=defaultVar) { // ... } ...then change the defaultVar value according to my needs.

What is a function with no arguments called?

A nullary or niladic function.


1 Answers

flip, which produces a new function with the first two arguments inversed, has already been mentioned as a straigtforward solution.

However, it's worth noting that Haskell defines a nice infix syntax for binary operators.

First of all, it's simply

sub = (-) 

With parentheses around, all operators are - syntactially too - ordinary functions. Now we can curry operators with some special syntax. Binding to the first operand:

addOne = (1 +) 

... and to the second

half = (/ 2) 

Thus your code becomes

map (-5) [1..5] 

Unfortunately, -5 is a number literal, but you get the point. :) Now since we can turn any function into a binary operator by putting backticks around it like in

f x y == x `f` y 

we can use this special operator syntax to write

map (`sub` 5) [1..5] 


Note: Currying the first argument is common, the second one - as in your case - nicely possible. But: I wouldn't do that for futher arguments. Haskell functions are written in a style that the common ones to curry are in the front for exactly that reason.

Using some special syntax for further arguments feels much too implicit for me. Just use the lambda and give the variables descriptive names.

like image 146
Dario Avatar answered Oct 04 '22 12:10

Dario