Haskell scripts to solve identity matrix

  • A+
Category:Languages

how to solve identity for a matrix using Haskell scripts? For example, if with this given type

 type Matrice a = [[a]]  identity :: Int -> Maybe (Matrice Int) 

How can it return the identity matrice for the given size? I know that identity matrice is a square matrice which has zero for all values, except the values on the top-left to bottom-right diagonal which are all one. With the condition of, if the size is less than 1, then the identity matrice isn't defined and Nothing is returned.

So say for example,

Prelude > identity 5           Just [[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]] Prelude > identity 2           Just [[1,0],[0,1]] 

I've tried

identity1 :: Int -> Int -> [Int] identity1 a b     | a == 0 []     | b == 0 (1:identity (a-1) (-1))     | otherwise = (0:identity' (a-1) (b-1))  identity2 :: Int -> Int -> Matrice Int identity2 a b     | b == 0 []     | otherwise = (0:identity1 (a-1) (b-1) : identity2 a (b-1)  


One short approach is to define the "infinite" identity matrix as

ii = (1 : repeat 0) : fmap (0:) ii 

The first row is 1 0 0 ...; each subsequent row is the row above it with a 0 prepended to it.

It should be obvious that the first n rows of the first n columns of the infinite identity matrix is In.

1 | 0 | 0 | 0 | 0 | 0 | --+   |   |   |   |   | 0   1 | 0 | 0 | 0 | 0 | ------+   |   |   |   | 0   0   1 | 0 | 0 | 0 | ----------+   |   |   |  ... 0   0   0   1 | 0 | 0 | --------------+   |   | 0   0   0   0   1 | 0 | ------------------+   | 0   0   0   0   0   1 | ----------------------+            .            .            .              .            .                . 

Given that, we just use take to obtain the appropriate-sized sub matrix. take n applied to each row will return the first n columns, and take n applied to the result takes just the first n rows.

type Matrix a = [[a]]  identity :: Int -> Maybe (Matrix Int) identity n | n <= 0 = Nothing            | otherwise = let ii = (1:repeat 0) : (fmap (0:) ii)                          in Just $ take n (take n <$> ii) 

If recursively defined infinite lists tie your brain in knots, you can also just define an enlarge function that generates In+1 from In. To do so, it is convenient to assume that I0 exists and is represented as an empty list.

enlarge :: Matrix Int -> Matrix Int enlarge [] = [[1]] enlarge i@(r:_) = (1:(0<$r)) : fmap (0:) i 

Then you can define identity :: Int -> Matrix Int by indexing an infinite list of identity matrices

identity n | n <= 0 = Nothing identity n = Just (identities !! n) 

where identities :: [Matrix Int] is built with either iterate

identities = iterate enlarge [] 

or Data.List.unfoldr:

identities = unfoldr (/x -> Just (x, enlarge x)) [] 

It's also worth noting that the infinite identity matrix is the fixed point of enlarge:

import Data.Function ii = fix enlarge 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: