Root Mean Square

RootMeanSquare is a curried constructor used to create a JS/JSON configuration object that represents a root mean square (RMS) operation.

const RootMeanSquare =
  (datatype = "Number") =>
  (operands = []) => ({
    tag: "RootMeanSquare",
    operands,
    datatype,
  })
 
export default RootMeanSquare
 

The first parameter to RootMeanSquare determines the datatype of the return value of the root mean square operation: Number (float) or Integer.

The second parameter is an array of operations, each of which must eventually evaluate to a numerical value. These are the operands for the function. They are squared, added together, and then the square root of the sum is returned.

The operand operations (add, subtract, etc.) may be nested to any depth, but the bottom (leaf) nodes must return values. Values are injected with injectors.

Because RootMeanSquare is curried, we can simplify our code by partial application, for example, const Rms = RootMeanSquare("Number"). This returns a function that takes the array of operand operations and returns a RootMeanSquare configuration object for working with floating point numbers.

See below for an example.

The rootMeanSquare function

We pass our configuration object to composeOperators, which composes the operations and returns a single function. This function takes an optional argument and returns the result of the calculation as a Right, e.g., { right: 42 }, or a Left with an array of Error objects, { left: [Error] }.

const rootMeanSquare = operation => (arg? => Either<Array<Error>, result>)

composeOperators works by recursing down through the operation object, calling the correct operator function based on the tag (e.g., "RootMeanSquare"), and composing the functions returned. composeOperators then returns this composed function. See composeOperators for a more detailed explanation.

The injectors are not called until this composed calculate function is run. Hence, evaluation is lazy: the values are not injected until the last moment.

See the injectors for a complete list of how values may be injected. See the list of operators for the full range of available mathematical operations.

Example

We use composeOperators to create a calculate function, passing it our RootMeanSquare operation object. We call the calculate function and pass it an (optional) argument to run our operation(s) and calculate the product.

Here our operation includes three operands. The first is a nested division operation of two constants, the second is a constant, and the third value is passed in via the optional argument to calculate.

The leaf nodes are either constants (using Constant) or a value passed directly to to the calculate function (using FromArgument).

Try leaving one of the numbers undefined to see an Error returned.