MyNixOS website logo
Description

Optics for the "matrix" package.

matrix-lens

Optics for the matrix package.

matrix lenses

That’s how it is with people. Nobody cares how it works as long as it works.

  • Councillor Hamann

Sparked by this reddit post.

Examples

The examples below make use of the following three matrices:

exampleInt :: Matrix Int
exampleInt = Matrix.fromLists
  [ [1, 2, 3]
  , [4, 5, 6]
  , [7, 8, 9]
  ]

exampleInvertible :: Matrix (Ratio Int)
exampleInvertible = Matrix.fromLists
  [ [ -3, 1 ]
  , [  5, 0 ]
  ]

exampleNotSquare :: Matrix Int
exampleNotSquare = Matrix.fromLists
  [ [10,   20,  30]
  , [40,   50,  60]
  , [70,   80,  90]
  , [100, 110, 120]
  ]

Accessing individual elements:

λ> exampleNotSquare ^. elemAt (4, 3)
120
λ> exampleInt & elemAt (2, 2) *~ 10
┌          ┐
│  1  2  3 │
│  4 50  6 │
│  7  8  9 │
└          ┘

Accessing individual columns:

λ> exampleInt ^. col 1
[1,4,7]
λ> exampleInt & col 2 . each *~ 10
┌          ┐
│  1 20  3 │
│  4 50  6 │
│  7 80  9 │
└          ┘

Accessing individual rows:

λ> exampleInt ^. row 1
[1,2,3]
λ> exampleInt & row 2 . each *~ 100
┌             ┐
│   1   2   3 │
│ 400 500 600 │
│   7   8   9 │
└             ┘

Manipulating all columns as a list:

λ> exampleInt ^. cols
[[1,4,7],[2,5,8],[3,6,9]]
λ> exampleInt & cols %~ reverse
┌       ┐
│ 3 2 1 │
│ 6 5 4 │
│ 9 8 7 │
└       ┘

Accessing all rows as a list:

λ> exampleInt ^. rows
[[1,2,3],[4,5,6],[7,8,9]]
λ> exampleInt & rows %~ map reverse
┌       ┐
│ 3 2 1 │
│ 6 5 4 │
│ 9 8 7 │
└       ┘
λ> exampleInt & partsOf (dropping 1 (rows . each)) %~ reverse
┌       ┐
│ 1 2 3 │
│ 7 8 9 │
│ 4 5 6 │
└       ┘

In addition to the above there are also switching and sliding Isos for both rows and columns which allow you to swap two arbitrary rows or columns or slide a row or column through the matrix to a different row or column (moving all intervening rows or columns over in the direction of the source row or column):

λ> exampleNotSquare ^. switchingRows 1 4
┌             ┐
│ 100 110 120 │
│  40  50  60 │
│  70  80  90 │
│  10  20  30 │
└             ┘
λ> exampleNotSquare ^. slidingRows 1 4
┌             ┐
│  40  50  60 │
│  70  80  90 │
│ 100 110 120 │
│  10  20  30 │
└             ┘

..and similary for switchingCols and switchingRows.

An Iso exists for accessing the matrix with a given row scaled:

λ> exampleInt ^. scalingRow 1 10
┌          ┐
│ 10 20 30 │
│  4  5  6 │
│  7  8  9 │
└          ┘

λ> exampleInt & scalingRow 1 10 . flattened  *~ 2
┌                ┐
│ -200 -400 -600 │
│    8   10   12 │
│   14   16   18 │
└                ┘

Any valid sub matrix can be accessed via the sub lens:

λ> exampleNotSquare ^. sub (2, 1) (3, 2)
┌         ┐
│  40  50 │
│  70  80 │
└         ┘

λ> exampleNotSquare & sub (2, 1) (3, 2) . rows %~ reverse
┌             ┐
│  10  20  30 │
│  70  80  60 │
│  40  50  90 │
│ 100 110 120 │
└             ┘

The transposition of the matrix can be accessed via the transposed Iso:

λ> exampleInt ^. transposed
┌       ┐
│ 1 4 7 │
│ 2 5 8 │
│ 3 6 9 │
└       ┘

λ> exampleInt & transposed . taking 4 flattened *~ 10
┌          ┐
│ 10 20  3 │
│ 40  5  6 │
│ 70  8  9 │
└          ┘

You can also traverse the flattened matrix:

λ> exampleInt ^.. flattened
[1,2,3,4,5,6,7,8,9]

which is more useful for making modifications:

λ> exampleInt & flattened . filtered even *~ 10
┌          ┐
│  1 20  3 │
│ 40  5 60 │
│  7 80  9 │
└          ┘
λ> exampleInt & dropping 4 flattened *~ 10
┌          ┐
│  1  2  3 │
│  4 50 60 │
│ 70 80 90 │
└          ┘

Accessing the diagonal:

λ> exampleInt ^. diag
[1,5,9]

λ> exampleInt & diag %~ reverse
┌       ┐
│ 9 2 3 │
│ 4 5 6 │
│ 7 8 1 │
└       ┘

λ> exampleInt & diag . each *~ 10
┌          ┐
│ 10  2  3 │
│  4 50  6 │
│  7  8 90 │
└          ┘

Accessing inverse matrix is possible via the inverted optic. Since not all matrices have inverses inverted is a prism:

λ> exampleInvertible ^? inverted
Just ┌             ┐
│ 0 % 1 1 % 5 │
│ 1 % 1 3 % 5 │
└             ┘

λ> exampleInvertible & inverted . flattened *~ 2
┌                   ┐
│ (-3) % 2    1 % 2 │
│    5 % 2    0 % 1 │
└                   ┘

Minor matrices can be accessed by specifying the (r, c) to be removed:

λ> exampleInt ^. minor (1, 2)
┌     ┐
│ 4 6 │
│ 7 9 │
└     ┘

λ> exampleInt & minor (1, 2) . flattened *~ 10
┌          ┐
│  1  2  3 │
│ 40  5 60 │
│ 70  8 90 │
└          ┘

An Iso exists for accessing a scaled version of a matrix:

λ> exampleInt ^. scaled 10
┌          ┐
│ 10 20 30 │
│ 40 50 60 │
│ 70 80 90 │
└          ┘

λ> exampleInt & minor (1, 1) . scaled 10 . flattened  +~ 1
┌                ┐
│    1    2    3 │
│    4 -510 -610 │
│    7 -810 -910 │
└                ┘

Getters for the matrix determinant and size are also provided:

λ> exampleInt ^. determinant
Just 0

λ> exampleInvertible ^. determinant
Just ((-5) % 1)

λ> exampleNotSquare ^. determinant
Nothing

λ> exampleInt ^. size
(3,3)
λ> exampleInvertible ^. size
(2,2)
λ> exampleNotSquare ^. size
(4,3)
Metadata

Version

0.1.0.0

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows