- A+

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 **I**_{n}.

`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 **I**_{n+1} from **I**_{n}. To do so, it is convenient to assume that **I**_{0} 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 `