Обратная матрица в Хаскеле
Я только начал изучать Хаскель.
И у меня есть вопрос. Я пытаюсь написать функцию, чтобы найти обратную матрицу.
Мой тип матрицы выглядит так:
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)
поскольку получение длины вектора в любом случае является операцией с постоянным временем.