pee*_*eer 8 haskell sum matrix fold foldable
我对矩阵列表求和,foldl1 (+)
因为我注意到sum
实际上返回的是左上角元素的和为1x1矩阵。
$ stack exec --resolver lts-12.5 --package matrix -- ghci
GHCi, version 8.4.3: http://www.haskell.org/ghc/ :? for help
Prelude> import Data.Matrix
Prelude Data.Matrix> t = [identity 2, identity 2] -- two 2x2 identity matrices
Prelude Data.Matrix> foldl1 (+) t
? ?
? 2 0 ?
? 0 2 ?
? ?
Prelude Data.Matrix> sum t
? ?
? 2 ?
? ?
Run Code Online (Sandbox Code Playgroud)
这对我来说是出乎意料的,LYAH建议sum = foldl1 (+)
¹甚至hlint建议我使用sum
而不是foldl1 (+)
' Removing error on []
'(附带的问题:如何优雅而[]
安全地对矩阵求和?)
为什么要sum /= foldl1 (+)
使用矩阵,为什么通常不总是这样sum == foldl1 (+)
?
或者,排除空列表的情况:
为什么不sum == foldl neutralElement (+)
呢?或者具体sum == foldl (+) (zero 2 2)
的[identity 2, identity 2]
?
自己的工作:
Prelude Data.Matrix> :t sum
sum :: (Foldable t, Num a) => t a -> a
Prelude Data.Matrix> :info sum
class Foldable (t :: * -> *) where
...
sum :: Num a => t a -> a
...
-- Defined in ‘Data.Foldable’
Run Code Online (Sandbox Code Playgroud)
的来源sum
是:
sum :: Num a => t a -> a
sum = getSum #. foldMap Sum
Run Code Online (Sandbox Code Playgroud)
的实例Matrix
是:
instance Foldable Matrix where
foldMap f = foldMap f . mvect
instance Num a => Num (Matrix a) where
fromInteger = M 1 1 . V.singleton . fromInteger
negate = fmap negate
abs = fmap abs
signum = fmap signum
-- Addition of matrices.
{-# SPECIALIZE (+) :: Matrix Double -> Matrix Double -> Matrix Double #-}
{-# SPECIALIZE (+) :: Matrix Int -> Matrix Int -> Matrix Int #-}
(M n m v) + (M n' m' v')
-- Checking that sizes match...
| n /= n' || m /= m' = error $ "Addition of " ++ sizeStr n m ++ " and "
++ sizeStr n' m' ++ " matrices."
-- Otherwise, trivial zip.
| otherwise = M n m $ V.zipWith (+) v v'
-- Substraction of matrices.
...
-- Multiplication of matrices.
...
Run Code Online (Sandbox Code Playgroud)
¹加上整数
由于Data.Matrix
例如用于Num
工具fromInteger
通过返回一个1x1矩阵,并且+
通过加入elementwise
(如果左边是比右侧大或错误),其截断右矩阵向左一个的尺寸。
的sum
是foldl (+) 0
,其与从一个1x1矩阵开始0
并截断所有矩阵的列表中的该大小。在foldl1 (+)
没有从整使矩阵,所以其结果是在列表中最小的矩阵的大小。
另外,sum = getSum #. foldMap Sum
是默认Foldable
实现,但被list实例覆盖为sum = foldl (+) 0
。
如果操作数的形状不同,直到版本0.3.1.1 的Data.Matrix
实现+
(如上所示)都会产生错误,但是在版本0.3.2.0中,它假定未经检查就具有相同的形状,而在版本0.3.3.0中,它假定相同的形状。再次更改(根据评论):
-- | Perform an operation element-wise.
-- The second matrix must have at least as many rows
-- and columns as the first matrix. If it's bigger,
-- the leftover items will be ignored.
-- If it's smaller, it will cause a run-time error.
-- You may want to use 'elementwiseUnsafe' if you
-- are definitely sure that a run-time error won't
-- arise.
Run Code Online (Sandbox Code Playgroud)
直到最新版本0.3.6.1的实现似乎都是相同的