转置矩阵时触发`head: empty list`错误,寻求解决方案
问题分析与解决
错误原因
你的代码抛出Prelude.head: empty list错误,核心问题出在递归终止条件不完整和冗余分支干扰:
trans的终止条件仅处理了[[]](单个空行的矩阵),但当转置到后期,矩阵变成[[],[]]这类多空行的结构时,无法匹配终止条件,会继续执行递归分支,调用transHead尝试取空列表的head,触发错误。transHead中的[[a],[b]]分支完全冗余,仅匹配两个单元素行的特殊情况,既不会覆盖多数场景,还会混淆递归逻辑。transTail未处理空行场景,当行被tail操作后变为空列表时,后续递归仍会尝试访问其head。
修正后的代码
可以简化逻辑,用标准的Haskell高阶函数替代手动递归,同时完善终止条件:
trans :: [[Int]] -> [[Int]] trans [] = [] -- 空矩阵直接返回空 trans xss | any null xss = [] -- 存在空行时终止递归 trans xss = map head xss : trans (map tail xss)
代码说明
map head xss:提取每一行的第一个元素,组成转置后的第一行。map tail xss:对每一行执行tail操作,得到去掉首元素后的子矩阵,递归转置这个子矩阵。- 终止条件
any null xss:只要矩阵中有任意一行是空列表,就停止递归,避免访问空列表的head。
原代码的手动递归修正(如果想保留手动实现)
如果坚持用手动递归实现transHead和transTail,需要完善终止条件:
trans :: [[Int]] -> [[Int]] trans [] = [] trans xss | any null xss = [] trans xss = transHead xss : trans (transTail xss) transHead :: [[Int]] -> [Int] transHead [] = [] transHead (xs:xss) | null xs = [] -- 遇到空行时停止 transHead (xs:xss) = head xs : transHead xss transTail :: [[Int]] -> [[Int]] transTail [] = [] transTail (xs:xss) | null xs = transTail xss -- 跳过空行 transTail (xs:xss) = tail xs : transTail xss
内容的提问来源于stack exchange,提问作者lilo
相关产品推荐
相关产品推荐

