JavaScript functional programing with compose function and Array.reduce - javascript

I am new to JavaScript Functional programming. In code below, compose can't work without setInterval outside it and clear as the first argument also does't give the compose initial value.
So my question is how can compose work without the setInterval?
const clear = () => console.clear()
const f1 = () => 2
const log = message => console.log(message)
const compose = (...fns) =>
arg =>
fns.reduce(
(composed, f) => f(composed),
arg
)
setInterval(
compose(clear, f1, log), 1000
)

compose(...fns) returns a function. When used with setInterval, it is being called implicitly by the JavaScript engine.
If you want to use it directly, you can do something like:
const clear = () => console.clear()
const f1 = () => 2
const log = message => console.log(message)
const compose = (...fns) =>
arg =>
fns.reduce(
(composed, f) => f(composed),
arg
)
compose(clear, f1, log)();

Related

How to get parameter from parent scope into child scope?

Having two functions one wrapping the other, how to pass a parameter down correctly? At the moment the console logging does not work.
const a = (v) => (v) => console.log(v);
a(2);
Passing a parameter in High order fn is easy as the value get set to closure
const a = v => () => {console.log(v)};
a(2)()
No matter how deep you go, parameter passed to fn get set to closure space when a fn having a parameter v either returns a fn or executes a fn which uses that parameter v
const a = v => () => () => () => {console.log(v)}
a(2)()()()
If you really want to work on two functions
const a = (v) => (a = v) => console.log(a);
a(2)()
What you did over there to define a lambda function within a function.
If you want it to work with a(2) you need to excecture the inner function (meaning to add () at the end), like this:
const a = (v) => (() => console.log(v))();
a(2);
This (() => console.log(v)) is a function, when you add () at the end it's actually activating that function, and that's why what you did, didn't work.
You have two v variables, and the inner one is shadowing the outer one since they have the same name. Unless you rename the inner v, there's no way to access the outer v from inside that function.

With flow types, is it possible to auto infer return value for function that takes another function as an argument?

Let's say I have a function that takes a function as an argument and returns another function that takes a value that it passes to the function passed as an argument:
const curry = f => x => f(x);
Is it possible to type this function using Flow Type in such a way that the return value of curry is determined by the function f passed in if that function has been typed?
I tried this:
const numToStr = (x: number): string => x.toString();
const curry = <F: Function>(f: F): (mixed => *) => (x: mixed): * => f(x);
const curried = curry(numToStr);
link
The result of passing the first argument is that the resulting function curried has a signature like this:
(((x: mixed) => any) | ((x: mixed) => empty))
This makes sense, either the result is empty or it's anything. What I'd hoped is that because numToStr is typed, that it'd be possible for Flow to understand that curried is really number => string.
Is there a way to do this that I've missed? If not, can anyone explain why.
Currying usually applies to the process of taking a function of two arguments and transforming it into a function of one argument that returns another function of one argument which returns the result.
In Flow it would look like this:
const curry = <A, B, C>(f: (A, B) => C): (A => (B => C)) => (x) => (y) => f(x, y);
const prefixNum = (prefix: string, x: number): string => prefix + x.toString();
const prefixed = curry(prefixNum);
const withHello = prefixed("hello ");
const result = withHello(3); // "hello 3"
Your version is a bit different. You are transforming a function of one argument into a function of zero arguments. This is more like lazy evaluation than currying: supply all of the arguments but only return a zero-argument function (sometimes called a "thunk"), which actually performs the computation when you call it. The implementation could look like this:
const makeLazy = <A, C>(f: A => C): (A => (() => C)) => (x) => () => f(x);
It's essentially the definition above, but with one of the types replaced with (). This should work how you want it to:
const numToStr = (x: number): string => x.toString();
const lazyNumToStr = makeLazy(numToStr);
const thunk = lazyNumToStr(3);
thunk(); // "3"

Is using sequence the right approach to give monadic arguments to a function of arity greater than 1?

See the following code snippet:
const
fun1 = () => Either.of(1),
fun2 = () => Either.of(2),
fun3 = () => Either.of(3),
fun4 = curry((x, y, z) => Either.of(x + y + z)),
fun5 = x => Either.of(x + 1),
fun6 = () => pipeK(
() => sequence(Either.of, [fun1(), fun2(), fun3()]),
apply(fun4),
fun5
)(),
result = fun6() // returns 7
fun4 requires 3 arguments and I'd like to give them only if all of them are right arguments. That is, sequence will apply each monadic value so I'll get them as a single right containg the raw fun1, fun2, fun3 return values.
Is this the recommended approach?
Click here for run the whole code snippet
No, I would not use sequence with an array and apply. I think the more idiomatic approach is to use ap:
const fun6 = () => chain(fun5, unnest(ap(ap(ap(Either.of(fun4), fun1()), fun2()), fun3())));
// or
const fun6 = () => chain(fun5, unnest(ap(ap(map(fun4, fun1()), fun2()), fun3())));
// or
const fun6 = () => Either.of(fun4).ap(fun1()).ap(fun2()).ap(fun3()).chain(identity).chain(fun5);
The equivalent in Haskell would be fun5 =<< join (fun4 <$> fun1 <*> fun2 <*> fun3). The unnest is needed when fun4 returns an Either, which might not be necessary.

Compose javascript functions with more than one argument

How can I convert this function composition into more readable format?
funcA(argumentA, funcB(argumentA, funcC(argumentA, argumentB)))
What I'd like to achieve is something more like this:
compose(funcC, funcB, funcA)(argumentA, argumentB)
I'm using this compose function implementation:
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))
The problem is I need argumentA in all function calls as a first parameter and every function returns a value to be passed as a second parameter to the next function. I know I could create separate function-returning functions and use them like so:
compose(funcCWithArg(argumentA), funcBWithArg(argumentA), funcAWithArg(argumentA))(argumentB)
but in my actual case there aren't only three of them, but many more and that would require some serious amount of code just to write them down. Is there a simpler way to do that?
EDIT: I can't use any external library. Only vanilla js.
Using vanilla JS,
const compose = (...fns) => (arg1, arg2) => fns.reduce((arg, f) => f(arg1, arg), arg2);
Explanation
compose becomes a function returning a function, which loops through the list of functions passed to it, passing the first argument to every function call.
Test
const sum = (a, b) => (a + b);
const mult = (a, b) => (a * b);
compose(sum, mult)(2, 3) === mult(2, sum(2, 3)); // true
It's not hard to write a function like this:
const link = (...fns) => (a, ...args) =>
fns.slice(1).reduce((val, fn) => fn(a, val), fns[0](a, ...args));
If you wanted it to be robust enough to handle errors gracefully, it would take more. But this should be a start.
You would use it like this:
const funcA = (x, y) => `funcA(${x}, ${y})`;
const funcB = (x, y) => `funcB(${x}, ${y})`;
const funcC = (x, y) => `funcC(${x}, ${y})`;
link(funcA, funcB, funcC)('argumentA', 'argumentB');
//=> "funcC(argumentA, funcB(argumentA, funcA(argumentA, argumentB)))"
You can see this in action on Runkit.
(And obviously you can do a reverse if you want the opposite argument order.)
First create new functions that are partial applications using bind. Then use the compose function you already have:
const funcA = (x, y) => `A(${x}, ${y})`;
const funcB = (x, y) => `B(${x}, ${y})`;
const funcC = (x, y) => `C(${x}, ${y})`;
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
const partials = (...fns) => (...args) => fns.map((f) => f.bind(this, ...args));
console.log(compose(...partials(funcA, funcB, funcC)("a"))("b"));
// Output:
// A(a, B(a, C(a, b)))
UPDATE
You can also build a single function that composes the partials with the first argument passed and then calls them with the other arguments. (I think this is what you want? I wasn't 100% sure what to do with more than two arguments.)
const partialCompose = (...fns) => (...args) => compose(...partials(...fns)(args[0]))(...args.slice(1));
console.log(partialCompose(funcA, funcB, funcC)("a", "b")); // same output as above

how to return function or promise based on call site?

I would like to know if you have some clean way for creating a function that works when called by itself returning a promise, and returns a function when chained in a .then.
example:
// returns a promise. use to start chains:
// eg: wait(400).then(...)
const wait_p = (t) => new Promise( resolve => setTimeout( resolve, t) );
// returns a function: use inside .then():
// eg: $get('whatever').then(wait_f(300))
const wait_f = (t) => () => wait_p(t)
what's the cleanest way to have both wait_p and wait_f merged in a single wait() function?
//hypotetically:
const put = (x) => () => console.log(x)
wait(1000)
.then(put('one'))
.then(wait(1000))
.then(put('two'))
Having a schizophrenic function is probably not a great idea, even if you could figure out how to do it. Choose one and use it. Either:
wait_f(1000)().then(wait_f(1000))...
or
wait_p(1000).then(() => wait_p(1000))...
Personally I often use a function like your wait_f, but I rarely find myself wanting to use it to start a promise chain.
I guess you could return a function with a then method:
const wait = t => {
var p = new Promise(resolve => setTimeout(resolve,t));
var func = () => p;
func.then = (...args) => p.then(...args);
return func;
}
wait(400).then(() => console.log('Hello'))
Promise.resolve().then(wait(500)).then(() => console.log('World'))

Categories

Resources