Currying in ES6: Exercises.
Questions:
- What is currying?
- What is partial application?
- What is the difference between curry and partial application?
- What is point-free style?
- What is function composition?
- How does currying help with function composition?
add2(a) => b => Number
Question: What does it mean to curry a function?
Given two numbers, a
and b
in curried form, return a Number
which is the sum of a
and b
.
add2(2)(3); // 5
add3(a) => b => c => Number
Questions:
- What is partial application?
- What is the difference between curry and partial application?
Given 3 numbers, curried or partially applied, return the sum of all 3 numbers.
Lodash and Ramda both supply curry functions that create auto-curried functions. Here's a function you can use to create add3
:
// Tiny, recursive autocurry
const curry = (
f, arr = []
) => (...args) => (
a => a.length === f.length ?
f(...a) :
curry(f, a)
)([...arr, ...args]);
This curry utility takes a function that takes any number of arguments and returns a function that will curry or partially apply as necessary depending on how many arguments you pass in to the returned function.
add3(1, 2, 3); // 6
add3(1, 2)(3); // 6
add3(1)(2, 3); // 6
add3(1)(2)(3); // 6
inc(n) => Number
Question: What is point-free style?
Use add2()
to create a new function that adds 1 to any number.
Your function should not have a reference to its argument in the function definition. In other words, it should be written in point free style. Write the function without using any of the following: =>
, function
, Function
, eval
.
inc(3); // 4
trace(label: s) => (value: v) => v, effects(log to console)
Given a label
and a value
in curried form, log a message to the console using template literal notation:
label: value
Usage:
trace('inc')(inc(3)); // inc: 4
compose(f: Function, g: Function) => Function
Question: What is function composition?
Given two functions, f
and g
, return a new function representing the composition: f ∘ g
(f
after g
).
Hint: In math notation, the application of
f ∘ g
is equivalent to(f ∘ g)(x)
which is equal tof(g(x))
. Where doesx
come from?
Usage:
const g = n => n + 1;
const f = n => n * 2;
const meaning = compose2(f, g);
meaning(20); // 42
compose(...fns: [...Functions]) => Function
Question: How does currying help with function composition?
Given any number of functions, fns
, e.g., f
, g
, h
, etc..., return a new function representing the composition of all given functions from right to left. In other words, compose(f, g, h)
represents the composition f ∘ g ∘ h
.
const composed = compose(
trace('after f'),
f,
trace('after g'),
g
);
composed(20); // 42
Hint: You can use a reducer function, but
Array.prototype.reduce()
probably won't give you what you need. Is there another form of reduce you can use?
Pipe is exactly like compose, but instead of working from right to left, it works left to right.
pipe(...fns: [...Function]) => Function
Given any number of functions, fns
, e.g., f
, g
, h
, etc..., return a new function representing the composition of all given functions from left to right. In other words, pipe(f, g, h)
represents the composition h ∘ g ∘ f
.
const piped = pipe(
f,
trace('after f'),
g,
trace('after g')
);
piped(20); // 41