sum of multiples of 3 and 5 below 1000 in node js code example

Example: javascript sum of all the multiples of 3 or 5 below 1000 running total

(() => {     // sum35 :: Int -> Int    const sum35 = n => {        // The sum of all positive multiples of        // 3 or 5 below n.        const f = sumMults(n);        return f(3) + f(5) - f(15);    };      // sumMults :: Int -> Int -> Int    const sumMults = n =>        // Area under straight line        // between first multiple and last.        factor => {            const n1 = quot(n - 1)(factor);            return quot(factor * n1 * (n1 + 1))(2);        };     // ------------------------- TEST --------------------------     // main :: IO ()    const main = () =>        fTable('Sums for n = 10^1 thru 10^8:')(str)(str)(            sum35        )(            enumFromTo(1)(8)            .map(n => Math.pow(10, n))        );      // ------------------------ GENERIC ------------------------     // enumFromTo :: Int -> Int -> [Int]    const enumFromTo = m =>        n => !isNaN(m) ? (            Array.from({                length: 1 + n - m            }, (_, i) => m + i)        ) : enumFromTo_(m)(n);      // quot :: Int -> Int -> Int    const quot = n =>        m => Math.floor(n / m);      // ------------------------ DISPLAY ------------------------     // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c    const compose = (...fs) =>        // A function defined by the right-to-left        // composition of all the functions in fs.        fs.reduce(            (f, g) => x => f(g(x)),            x => x        );      // fTable :: String -> (a -> String) -> (b -> String)    //                      -> (a -> b) -> [a] -> String    const fTable = s =>        // Heading -> x display function ->        //           fx display function ->        //    f -> values -> tabular string        xShow => fxShow => f => xs => {            const                ys = xs.map(xShow),                w = Math.max(...ys.map(length));            return s + '\n' + zipWith(                a => b => a.padStart(w, ' ') + ' -> ' + b            )(ys)(                xs.map(x => fxShow(f(x)))            ).join('\n');        };      // length :: [a] -> Int    const length = xs =>        // Returns Infinity over objects without finite        // length. This enables zip and zipWith to choose        // the shorter argument when one is non-finite,        // like cycle, repeat etc        'GeneratorFunction' !== xs.constructor.constructor.name ? (            xs.length        ) : Infinity;      // list :: StringOrArrayLike b => b -> [a]    const list = xs =>        // xs itself, if it is an Array,        // or an Array derived from xs.        Array.isArray(xs) ? (            xs        ) : Array.from(xs);      // str :: a -> String    const str = x =>        Array.isArray(x) && x.every(            v => ('string' === typeof v) && (1 === v.length)        ) ? (            x.join('')        ) : x.toString();      // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        // The first n elements of a list,        // string of characters, or stream.        xs => 'GeneratorFunction' !== xs        .constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat.apply([], Array.from({            length: n        }, () => {            const x = xs.next();            return x.done ? [] : [x.value];        }));      // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = f =>        // Use of `take` and `length` here allows zipping with non-finite lists        // i.e. generators like cycle, repeat, iterate.        xs => ys => {            const n = Math.min(length(xs), length(ys));            return (([as, bs]) => Array.from({                length: n            }, (_, i) => f(as[i])(                bs[i]            )))([xs, ys].map(                compose(take(n), list)            ));        };     // ---    return main();})();