Skip to content

Instantly share code, notes, and snippets.

@m0n4d1
Last active July 7, 2022 04:17
Show Gist options
  • Save m0n4d1/4667242284769192a2816453954e2219 to your computer and use it in GitHub Desktop.
Save m0n4d1/4667242284769192a2816453954e2219 to your computer and use it in GitHub Desktop.
Pure Functional Matrix Operations
// Pure Functional Matrix Operations
// built using partially applied curried functions
// I wrote function signatures with pseudo types to help me remember what things do
// All these functions gradually compose into ones capable various matrix operations
//---------------------------------------
// BUILDING BLOCKS
// Checks if item is not undefined
// a -> bool
const exists = a => (
a !== undefined
)
// n -> n -> n
const add = x => y => (
x + y
)
// n -> n -> n
const subtract = x => y => {
x - y
}
// Multiply 2 values
// n -> n -> n
const mult = x => y => (
x * y
)
// Folds a function over an array
// (a -> a -> a) l -> a
const fold = f => l => (
exists(l[1]) ? f(l[0])(fold(f)(l.slice(1)))
: l[0]
)
// Returns the sum of elements in an array
// l -> n
const sum = fold(add)
// Applies a function to every item in an array
// (a -> a) -> l -> l
const map = f => l => (
exists(l[1]) ? [f(l[0]), ...map(f)(l.slice(1))]
: [f(l[0])]
)
// Accepts a binary function to operate on items at the same index in 2 seperate arrays returning a single array
// (a -> a -> a) -> l -> l -> l
const mergeArrsWith = f => l1 => l2 => (
exists(l1[1]) && exists(l2[1]) ? [f(l1[0])(l2[0]), ...mergeArrsWith(f)(l1.slice(1))(l2.slice(1))]
: [f(l1[0])(l2[0])]
)
// Drills down into multi-dimensional array n levels deep and applies map
// n -> (a -> a) -> l -> l
const deepMap = n => f => l => (
n > 1 ? map(x => deepMap(n-1)(f)(x))
: n === 1 && map(x => map(f)(x))(l)
)
// (a -> a) -> l -> l
const matrixMap = deepMap(1)
// These functions merge arrays together with specific binary functions such that operands are elements at identical indexes
// l -> l -> l
const sumArrays = mergeArrsWith(add)
const subtractArrays = mergeArrsWith(subtract)
const multArrays = mergeArrsWith(mult)
//--------------------------------------------------
// MATRIX OPERATIONS
// These functions all return a singular matrix
// l -> l -> l
const matrixAdd = mergeArrsWith(sumArrays)
const matrixSubtract = mergeArrsWith(subtractArrays)
// n -> l -> a
const matrixScalar = k => A => (
matrixMap(mult(k))(A)
)
// l -> l
const transpose = A => (
exists(A[0][1]) ? [map(row => row[0])(A), ...transpose(map(row => row.slice(1))(A))]
: [map(row => row[0])(A)]
)
// l -> l -> n
const matrixProduct_ = A => B => (
map(rowA => map(rowB => sum(multArrays(rowA)(rowB)))(B))(A)
)
// This just froces B through a transpose on input rather than running it for every rowA in A
const matrixProduct = A => B => matrixProduct_(A)(transpose(B))
//--------------------------------------------------
//Tests -- TODO
const matrix1 = [
[1,2,3],
[4,5,6]
]
const matrix2 = [
[1,2],
[3,4],
[5,6]
]
console.log(matrixProduct(matrix1)(matrix2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment