Reputation: 106
I came up with this function (f1, f2, val) => f1(f2(val), val) (javascript notation) and it seemed like it would be useful/common for functional programming. I wanted to know if this function already exists and if it does what it's proper name would be.
(an equivalent question would be what is (f1, f2, val) => f1(f2(val)) called? and the equivalent answer would be composition)
Upvotes: 1
Views: 141
Reputation:
This is the chain
function of the monad API specialized to the function type. The good thing about monads is that you can apply them for any type in a mechanical way and they always work as expected:
// your combinator in curried form with the two first arguments flipped
const chain = g => f => x => f(g(x)) (x);
// 2nd part of the monad interface
const of = x => _ => x;
const add = x => y => x + y;
/* ridiculously complicated Fibonacci algorithm
just to demonstrate the predictability of monads */
const fib = n =>
n > 1
? chain(of(n - 1)) (w =>
chain(of(n - 2)) (x =>
chain(fib(w)) (y =>
chain(fib(x)) (z =>
of(y + z)))))
: of(n);
const main = fib(10);
console.log(
main()); // 55
Once you have grasped how monads work it isn't so hard anymore to understand the given example for the function type and any example for any type that implements the monad type class.
Upvotes: 0
Reputation: 64923
It looks like the S
combinator variation:
const S = f => g => x => f (x) (g (x))
Probably you might be able to refactor your code to accomodate to S
combinator.
Upvotes: 0
Reputation: 7036
It's just bind (>>=) operator of function monad.
In Haskell, function is represented as a -> b
, which can be considered as an operator (->) takes two parameters and rewritten as (->) a b
. We can partial apply (->)
with one parameter, (->) a
.
(->) a
is a functor and monad. As a monad, it's definition is
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
In ramda, it's chain function.
Upvotes: 2
Reputation: 14179
First example looks like a branch/converge function, where the second argument is simply passed as identity.
const a = (f1, f2, val) => f1(f2(val), val);
const b = (f1, f2, val) => R.converge(f1, [f2, R.identity])(val);
const f1 = (a, b) => a + b;
const f2 = (a) => a * 2;
console.log(
a(f1, f2, 50),
);
console.log(
b(f1, f2, 50),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
Second example is simply a compose function...
const a = (f1, f2, val) => f1(f2(val));
const f1 = (a) => a * 2;
const f2 = (a) => a + 100;
console.log(
a(f1, f2, 50),
);
console.log(
R.compose(f1, f2)(50),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
Upvotes: 0
Reputation: 18901
This looks like Ramda's chain method to me:
If second argument is a function, chain(f, g)(x) is equivalent to f(g(x), x).
So:
R.chain(R.append, R.sum)([1, 2, 3]);
is similar to:
R.append(R.sum([1, 2, 3]), [1, 2, 3]);
//=> [1, 2, 3, 6]
Whether the common name for such pattern is chain
I am not sure. Functional programming sometimes has impenetrable lingo IMHO.
Upvotes: 0