matrix-lens: Optics for the "matrix" package

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

See README at https://github.com/interosinc/matrix-lens#readme


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.0.0
Change log ChangeLog.md
Dependencies base (>=4.7 && <5), lens (>=4.19.2 && <4.20), matrix (>=0.3.6 && <0.4), vector (>=0.12.1 && <0.13) [details]
License BSD-3-Clause
Copyright 2020 Interos, Inc.
Author Interos, Inc.
Maintainer jevans@interos.ai
Category Math
Home page https://github.com/interosinc/matrix-lens#readme
Bug tracker https://github.com/interosinc/matrix-lens/issues
Source repo head: git clone https://github.com/interosinc/matrix-lens
Uploaded by lgastako at 2020-07-07T06:38:06Z

Modules

[Index] [Quick Jump]

Flags

Manual Flags

NameDescriptionDefault
developer

Developer mode -- stricter handling of compiler warnings.

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for matrix-lens-0.1.0.0

[back to package description]

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)