Обратная матрица в Хаскеле

Я только начал изучать Хаскель.
И у меня есть вопрос. Я пытаюсь написать функцию, чтобы найти обратную матрицу.
Мой тип матрицы выглядит так:

data Matrix a = M 
    { nrows :: !Int
    , ncols :: !Int
    , mvect :: V.Vector (V.Vector a)
    } deriving Eq

Также у меня есть fromLists функция.
Функция поиска определителя выглядит так:

det :: Num a => Matrix a -> a
det (M 1 1 v) = V.head (V.head v)
det m =
    sum [ (-1)^(i-1) * m ! (i,1) * det (minorMatrix i 1 m) | i <- [1 .. nrows m] ]

Итак, мой код для поиска обратной матрицы:

coords :: Matrix a -> [[(Int, Int)]]
coords = zipWith (map . (,)) [0..] . map (zipWith const [0..])

delmatrix :: Int -> Int -> Matrix a -> Matrix a
delmatrix i j = dellist i . map (dellist j)
    where dellist i xs = take i xs ++ drop (i + 1) xs

mapMatrix :: (a -> a) -> Matrix a -> Matrix a
mapMatrix f = map (map f)

cofactor :: Num a => Int -> Int -> Matrix a -> a
cofactor i j m = ((-1) ** fromIntegral (i + j)) * det (delmatrix i j m)

cofactorM :: Matrix a -> Matrix a
cofactorM m = map (map (\(i,j) -> cofactor j i m)) $ coords m

inverse :: (Num a, Fractional a) => Matrix a -> Matrix a
inverse m = mapMatrix (* recip deter) $ cofactorM m
    where deter = det m

А что у меня на консоли:

Prelude> :r
[1 of 1] Compiling Matrixlab        ( Matrixlab.hs, interpreted )

Matrixlab.hs:120:38:
    Couldn't match expected type `Matrix a' with actual type `[a0]'
    Expected type: Matrix a -> [[Int]]
      Actual type: [a0] -> [b0]
    In the return type of a call of `map'
    In the second argument of `(.)', namely
      `map (zipWith const [0 .. ])'

Matrixlab.hs:123:17:
    Couldn't match expected type `Matrix a' with actual type `[a0]'
    Expected type: [a0] -> Matrix a
      Actual type: [a0] -> [a0]
    In the return type of a call of `dellist'
    In the first argument of `(.)', namely `dellist i'

Matrixlab.hs:127:15:
    Couldn't match expected type `Matrix a' with actual type `[a0]'
    Expected type: Matrix a -> Matrix a
      Actual type: [a0] -> [b0]
    In the return type of a call of `map'
    In the expression: map (map f)

Matrixlab.hs:130:24:
    Could not deduce (Floating a) arising from a use of `**'
    from the context (Num a)
      bound by the type signature for
                 cofactor :: Num a => Int -> Int -> Matrix a -> a
      at Matrixlab.hs:130:1-71
    Possible fix:
      add (Floating a) to the context of
        the type signature for
          cofactor :: Num a => Int -> Int -> Matrix a -> a
    In the first argument of `(*)', namely
      `((- 1) ** fromIntegral (i + j))'
    In the expression:
      ((- 1) ** fromIntegral (i + j)) * det (delmatrix i j m)
    In an equation for `cofactor':
        cofactor i j m
          = ((- 1) ** fromIntegral (i + j)) * det (delmatrix i j m)

Matrixlab.hs:133:15:
    Couldn't match expected type `Matrix a' with actual type `[[a]]'
    In the expression:
      map (map (\ (i, j) -> cofactor j i m)) $ coords m
    In an equation for `cofactorM':
        cofactorM m = map (map (\ (i, j) -> cofactor j i m)) $ coords m
Failed, modules loaded: none.

Помоги мне, пожалуйста.

1 ответ

Решение

Прежде всего, если вы хотите использовать векторы, вы должны использовать векторы. Если вы собираетесь конвертировать их обратно и из списков все время, вы должны просто придерживаться списков. Векторный пакет предоставляет все функции, которые есть в списках для Vector тип. Так что вы должны их использовать. На самом деле, почти всегда будет легче работать с Vector функции, так как они дают вам встроенный доступ к индексу элемента. Если вы не знаете, какие функции у вас есть, взгляните на документы.

Вы также не можете притворяться, что ваш Matrix эквивалентно списку списков и ожидать, что компилятор будет знать, о чем вы говорите. Вы должны взять векторы из Matrix конструктор, использующий сопоставление с образцом, оперирует ими и помещает их обратно. Например:

import qualified Data.Vector as V

cofactorM :: Floating a => Matrix a -> Matrix a
cofactorM m@(M x y v) = M x y $ (V.imap $ \i -> V.imap $ \j -> const (cofactor i j m)) v 

cofactor :: Floating a => Int -> Int -> Matrix a -> a
cofactor ...

Имейте в виду, что Vector индексируется нулем, а ваш det Функция подразумевает, что ваши столбцы и строки проиндексированы. Вам придется компенсировать это.

Наконец, нет веских причин для упаковки количества строк и столбцов в Vector (Vector a) поскольку получение длины вектора в любом случае является операцией с постоянным временем.

Другие вопросы по тегам