***Exception: Prelude.head empty List. What is the base case?

百般思念 提交于 2020-01-15 05:03:46

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!