If we want to sum numeric values over a range of lines or drafts, we can write a reusable sum function in terms of Array.reduce:
// sum :: [Num] -> Num
const sum = xs =>
xs.reduce((a, x) => a + x, 0);
Starting with 0 as an accumulator seed value, it adds each current item x to the accumulator a, and returns the sum of the whole list.
So, if we have mapped each line in our draft to a corresponding number,
(for example the number of minutes expressed by a string like 2h 30m
at the end of the line)
draft.content
.split('\n')
.map(minsFromHMstring)
where minsFromHMstring might be something like:
// minsFromHMstring :: String -> Int
const minsFromHMstring = s => {
const m = /\s*(\d+)h\s+(\d+)m\s*$/.exec(s);
return Boolean(m) ? (
(60 * parseInt(m[1], 10)) + parseInt(m[2], 10)
) : 0;
};
We can just apply sum to this list of numbers:
(() => {
// main :: () -> IO Int
const main = () => {
const intMins = sum(
draft.content
.split('\n')
.map(minsFromHMstring)
);
return (
alert(intMins.toString()),
intMins
);
};
// sum :: [Num] -> Num
const sum = xs =>
xs.reduce((a, x) => a + x, 0);
// minsFromHMstring :: String -> Int
const minsFromHMstring = s => {
const m = /\s*(\d+)h\s+(\d+)m\s*$/.exec(s);
return Boolean(m) ? (
(60 * parseInt(m[1], 10)) + parseInt(m[2], 10)
) : 0;
};
return main();
})();