用 Haskell 实现的矩阵运算#
提示
这是一篇迁移自 Jekyll 的文章,如有格式问题,可到 ⛺ SilverRainZ/bullet 反馈
这学期开线性代数, 虽然我一向不喜欢数学, 本着将Haskell运用到实践中的精神, 想把上课教的几个矩阵运算写出来...虽然调试了半天, 回头一看, 好吧原来这么久简单的东西花了我那么多时间.
虽然到现在的我都没把趣学指南看完因为课有点多事实上是太懒了, 只看到了State Monad这里吧, 还不是太懂, 一旦碰到「作为Monad值的函数」,「作为Applicate值的函数」这种东西我就抓瞎了.
说回矩阵吧, 用Haskell写这个还是挺爽的, 相较于C来说:
不用和各种数组下标打交道
经常编译不过, 但一旦通过编译, 往往就得到正确的结果了
函数出乎意料地短, 数乘和矩阵加减本来都是用递归实现的, 写完后发现原来分别可以用map和zipWith来替代, 一下子长度就缩短了一半不止
各种类型错误让我想起了以前写Delphi的时候...
实现矩阵转置的时候卡了一下, 我原来写的是
transpose :: Matrix -> Matrix
transpose (Matrix []) = Matrix []
transpose (Matrix ys) = map head ys : transpose (Matrix $ map tail ys)
一直爆empty list exception, 因为pattern matching 不到 ys, 最后一步是[[],[]...]
而不是[]
, 上网查了一下矩阵转置函数才知道可以用[]:_
来匹配.
对于矩阵乘法, 我采取的是将右边那个矩阵转置, 这样就可以简化成行乘行, 左边矩阵拆成单行乘过去.
在用$
的时候总是遇到问题...总是报错, 也不知道为什么...我把简单地$当成让函数右结合的操作符,
但是如果写: getMartix $ Matrix xs `mmul
ys` 就错误.
看来理解还是有偏差的.
下面的代码分别实现了:
矩阵加法 plus
矩阵减法 sub
矩阵数乘 smul
矩阵乘积 mmul
矩阵的Eq实例和show实例
到底乘法用的是 multiplication 还是 product 呢... 好奇怪.
因为定义矩阵直接用了 [[Int]]
, 无法限制每个list的长度,
所以并不能保证这个Matrix里面肯定是一个符合定义的矩阵, 这个不知道怎么加以限制.
看看接下来教的什么或许可以再往代码里加点东西, 改天看看别人是怎么写的.
data Matrix = Matrix {getMartix :: [[Int]]}
smul :: Int -> Matrix -> Matrix
i `smul` Matrix xs = Matrix $ map (map (*i)) xs
plus :: Matrix -> Matrix -> Matrix
Matrix xs `plus` Matrix ys = Matrix $ zipWith (zipWith (+)) xs ys
sub :: Matrix -> Matrix -> Matrix
Matrix xs `sub` Matrix ys = Matrix $ zipWith (zipWith (-)) xs ys
transpose :: Matrix -> Matrix
transpose (Matrix ([]:_)) = Matrix []
transpose (Matrix xs) =
Matrix $ map head xs : getMartix (transpose $ Matrix $ map tail xs)
mmul :: Matrix -> Matrix -> Matrix
Matrix [] `mmul` _ = Matrix []
Matrix (x:xs) `mmul` ys =
Matrix $ (mul_ x $ getMartix (transpose ys)) : getMartix (Matrix xs `mmul` ys)
mul_ :: [Int] -> [[Int]] -> [Int]
mul_ _ [] = []
mul_ x (y:ys) = sum (zipWith (*) x y) : mul_ x ys
instance Eq Matrix where
Matrix [] == Matrix [] = True
Matrix (x:xs) == Matrix (y:ys) =
length x == length y && and (zipWith (==) x y) && Matrix xs == Matrix ys
instance Show Matrix where
show (Matrix []) = ""
show (Matrix (x:xs)) = show x ++ "\n" ++ show (Matrix xs)
如果你有任何意见,请在此评论。 如果你留下了电子邮箱,我可能会通过 回复你。