Matrix multiplication: Difference between revisions
Content added Content deleted
(→JS ES6: Adjusted primitives, tidied.) |
|||
Line 3,756: | Line 3,756: | ||
===ES6=== |
===ES6=== |
||
<lang JavaScript>((() => { |
<lang JavaScript>((() => { |
||
"use strict"; |
|||
// matrixMultiply :: Num a => [[a]] -> [[a]] -> [[a]] |
// matrixMultiply :: Num a => [[a]] -> [[a]] -> [[a]] |
||
Line 3,762: | Line 3,762: | ||
b => { |
b => { |
||
const cols = transpose(b); |
const cols = transpose(b); |
||
return map( |
return a.map( |
||
compose( |
compose( |
||
f => cols.map(f), |
|||
dotProduct |
dotProduct |
||
) |
) |
||
); |
|||
}; |
}; |
||
Line 3,774: | Line 3,775: | ||
compose(sum, zipWith(mul)(xs)); |
compose(sum, zipWith(mul)(xs)); |
||
// |
// ---------------------- TEST ----------------------- |
||
const main = () => |
const main = () => |
||
JSON.stringify(matrixMultiply( |
JSON.stringify(matrixMultiply( |
||
Line 3,788: | Line 3,790: | ||
])); |
])); |
||
// |
// --------------------- GENERIC --------------------- |
||
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c |
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c |
||
const compose = (...fs) => |
const compose = (...fs) => |
||
// A function defined by the right-to-left |
|||
// composition of all the functions in fs. |
|||
fs.reduce( |
fs.reduce( |
||
(f, g) => x => f(g(x)), |
(f, g) => x => f(g(x)), |
||
Line 3,797: | Line 3,802: | ||
); |
); |
||
// flip :: (a -> b -> c) -> b -> a -> c |
|||
const flip = f => |
|||
⚫ | |||
// 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 |
|||
(Array.isArray(xs) || 'string' === typeof xs) ? ( |
|||
⚫ | |||
) : Infinity; |
|||
// map :: (a -> b) -> [a] -> [b] |
|||
const map = f => |
|||
// The list obtained by applying f |
|||
// to each element of xs. |
|||
// (The image of xs under f). |
|||
xs => xs.map(f); |
|||
// mul :: Num a => a -> a -> a |
// mul :: Num a => a -> a -> a |
||
const mul = a => |
const mul = a => |
||
b => a * b; |
b => a * b; |
||
// sum :: (Num a) => [a] -> a |
// sum :: (Num a) => [a] -> a |
||
Line 3,826: | Line 3,812: | ||
xs.reduce((a, x) => a + x, 0); |
xs.reduce((a, x) => a + x, 0); |
||
// take :: Int -> [a] -> [a] |
|||
// take :: Int -> String -> String |
|||
const take = n => |
|||
// The first n elements of a list, |
|||
// string of characters, or stream. |
|||
xs => xs.slice(0, n); |
|||
// transpose :: [[a]] -> [[a]] |
// transpose :: [[a]] -> [[a]] |
||
Line 3,837: | Line 3,817: | ||
// The columns of the input transposed |
// The columns of the input transposed |
||
// into new rows. |
// into new rows. |
||
// |
// Simpler version of transpose, assuming input |
||
// rows of even length. |
|||
Boolean(rows.length) ? rows[0].map( |
|||
(_, i) => rows.flatMap( |
|||
⚫ | |||
) |
) |
||
) : []; |
) : []; |
||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] |
||
Line 3,849: | Line 3,831: | ||
// custom function, rather than with the |
// custom function, rather than with the |
||
// default tuple constructor. |
// default tuple constructor. |
||
xs => ys => |
xs => ys => xs.map( |
||
(x, i) => f(x)(ys[i]) |
|||
⚫ | |||
lng = Math.min(length(xs), length(ys)), |
|||
0, Math.min(xs.length, ys.length) |
|||
); |
|||
.map((x, i) => f(x)(vs[i])); |
|||
}; |
|||
// MAIN --- |
// MAIN --- |