Reputation: 121
I'm trying to write a function composition that partially applies an argument at each step and ends up calling a curried two-argument function.
There is a set of example functions to compose. I removed the calculations that there are supposed to do as they are not relevant to the problem but let's assume that every argument is required.
const getDayLimit = () => {
return 10
}
const getIpCount = ip => dayLimit => {
return 99
}
const getIp = (deviceId, headerIp) => {
// TODO: use Result monad to handle errors
if (!deviceId && !headerIp) {
throw new Error('Ip not provided')
}
return deviceId || headerIp
}
And the composition attempt:
const validateIp = R.compose(
f => f(getDayLimit()),
getIpCount,
getIp
)
validateIp(1, 2)
In the first step, getIp
received two values and based on them returns an ip that is then partially applied to getIpCount
, now the composition return a function that expects the dayLimit
argument that needs to be computed first.
The plain way of doing this could be: f => f(getAccountLimit())
.
I'd like to remove such function creation f => f... and pass it point-free.
Here's a helper function that solves this but is not handling all cases such as passing arguments to the result
function:
const applyResult = result => f => R.compose(f, result)()
then I could do:
const result = R.compose(
applyResult(getDayLimit),
getIpCount,
getIp
)
It seems too hacky for me and not substantial for my further use. I'd rather avoid writing my own helper function for this kind of problem.
Is there a functional way of computing arguments before partially applying them to a function? It seems to be a pretty common case in my mind, though perhaps I'm not thinking about the problem correctly.
Is my thinking incorrect about this problem and function composition?
What is a good approach to handling such a case with a function with two parameters in a composition?
Can this case of partially applying function arguments with each step be handled in a function composition?
Thank you!
Upvotes: 1
Views: 205
Reputation: 18931
I think I would use a continuation which, as I understand it, represents a computation that has been interrupted:
const cont = x => f => f(x);
With a continuation, you get x before f. Instead of doing f(x)
you do cont(x)(f)
which behind the scene just does f(x)
for you.
At the time of composing the functions together you already know the value of x
which is getDayLimit()
, you just don't know the value of f
yet which is known only when result
is applied to the first two initial parameters.
So here's what I'd do:
const result = R.compose( cont(getDayLimit())
, getIpCount
, getIp);
Is there a functional way of computing arguments before partially applying them to a function?
I would simply note that you apply a function to a value (not the other way round)
Upvotes: 2