Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass the second parameter to a Haskell function that takes 3 parameters?

I am learning Haskell now, I am just really curious about this. for example:

minus :: Int -> Int -> Int -> Int
minus x y z = x - y - z

what if I wanna pass y to the function [minus] first instead of x? I want a function [minus x 5 z] I don't want this

minusy10 x z = minus x 10 z

if I have to define a new function to achieve this, I feel like it lost some "Haskell elegance".

like image 372
PengHX Avatar asked Oct 18 '25 23:10

PengHX


2 Answers

Your minus10 is a very idiomatic way to do it; often this is bound inside a where clause so that it doesn't clutter the top-level API. flip minus 10 and (`minus` 10) are also common choices. Those two choices work only for filling in the second argument; more generally, to fill in an nth argument, lambdas generalize better, as in \x -> minus x 10.

like image 139
Daniel Wagner Avatar answered Oct 20 '25 21:10

Daniel Wagner


Fundamentally, you're asking how you can write minusy10 without explicitly naming its arguments. And, clearly, you also don't want to cheat by moving them into a lambda:

minusy10 = \x z -> minus x 10 z

What you want to do is writing minusy10 in "point-free style".

This is easily done in this case, as suggested in the other answer, but in the more general case, you might want to refer to pointfree.io, which will give you one possible way (but there might exist more) of writing a function in point-free style.

In this specific case, it comes up with the solution flip minus 10 (which is possibly not the most readable one; I'd call (`minus` 10) more readable, instead).

On the other hand, and with reference to your feeling that

if I have to define a new function to achieve this, I feel like it lost some "Haskell elegance"

it's worth taking into account that point-free style can make things less readable, if overused. In fact, even for very simple functions that you can read and understand in the blink of eye, such as this,

f x y = x + y*y

point-free style can result in something which is the opposite of readable (and actually even longer!):

f = (. join (*)) . (+)

So I'd say there's a balance between point-free style and "point-full" (?) style. Where's this balance? In my opinion one should target maximum readability, which is different from "parse-bility".

What I mean is that

subtract2 x = x - 2

is easy to parse, and fairly easy to read, but

subtract2 = (-2)

is even easier to read.

In your original example, the point-free form (`minus` 10) is fairly readable (but I would actually question the name you've given to minus, which makes me think of a binary (-)-like function, whereas it is ternary).

like image 37
Enlico Avatar answered Oct 20 '25 21:10

Enlico