问题
I am writing a function of getting the product of 2 matrix.
transpose' :: [[a]] -> [[a]]
transpose' [[]] = []
transpose' m = (map head m) : transpose' (map tail m)
dotProduct :: [Int] -> [Int] -> Int
dotProduct [] [] = 0
dotProduct (x:xs) (y:ys) = (x*y) + dotProduct xs ys
matrixProduct :: [[Int]] -> [[Int]] -> [[Int]]
matrixProduct [] _ = []
matrixProduct (x:xs) y = (map (dotProduct x) (transpose' y)):matrixProduct xs y
I always get something like [[2,2, ***Exception: Prelude.head empty List
Is it because I have wrong base case for the function?
I am not sure what that should be.
回答1:
I fixed the issues I found in your solution and this is what I would get:
transpose :: [[a]] -> [[a]]
transpose [] = repeat []
transpose (m:ms) = zipWith (:) m (transpose ms)
dotProduct :: [Int] -> [Int] -> Int
dotProduct xs ys = sum $ zipWith (*) xs ys
matrixProduct :: [[Int]] -> [[Int]] -> [[Int]]
matrixProduct xs ys = [ [dotProduct x y | y <- transpose ys ] | x <- xs ]
as you can see this should be really close to the row * col
definition of matrix-multiplication (the rows of a matrix in your representation are just the elements of the outer-list and the columns are the elements of the transposed matrix outer-list)
Aside from this I simplified your dotProduct
a bit (but yours was fine) and
fixed your transpose'
- which by the way was the source of your error!
I think the basic idea was right but you got into trouble with the base case (which is []
not [[]]
) and the way you should map the first row to the transposed rest - also note that you can use repeat []
which will give you an infinite list of []
as zipWith
will deal with it just fine - if you use []
instead your recursive case will break at zipWith (:) m [] == []
and bubble up to just []
my transpose
is a bit different to yours and maybe to complicated - the problem with yours is that one or more list inside m
could be empty which will cause head
and tail
to fail - so you have to guard this case:
transpose' :: [[a]] -> [[a]]
transpose' m
| and (map (not . null) m) = (map head m) : transpose' (map tail m)
| otherwise = []
map (not . null) m
will check each row if it is non-empty (result: [bool]
)and (map (not . null) m)
asserts that all rows are non-empty
来源:https://stackoverflow.com/questions/32944035/exception-prelude-head-empty-list-what-is-the-base-case