まず、 直接再帰の代わりにmirrorXY'
高階関数map
を使用して記述できます。iterate
mirr m = map (map head) . iterate (map tail) $ m
...そして、あなたが発見したように、これは空のリストにヒットすると爆発します:
*Main> map (map head) . iterate (map tail) $ [[1..4],[2..5],[3..6]]
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[*** Exception: Prelude.head: empty list
最初の部分なしで試してみましょう:
*Main> iterate (map tail) $ [[1..4],[2..5],[3..6]]
[[[1,2,3,4],[2,3,4,5],[3,4,5,6]],[[2,3,4],[3,4,5],[4,5,6]],[[3,4],[4,5],[5,6]],[
[4],[5],[6]],[[],[],[]],[*** Exception: Prelude.tail: empty list
*Main>
[]
したがって、修正は簡単です。入力リストでを押すのをやめるだけです。
*Main> takeWhile (not.null.head) . iterate (map tail) $ [[1..4],[2..5],[3..6]]
[[[1,2,3,4],[2,3,4,5],[3,4,5,6]],[[2,3,4],[3,4,5],[4,5,6]],[[3,4],[4,5],[5,6]],[
[4],[5],[6]]]
したがって、関数は
mirr xs = map (map head) . takeWhile (not.null.head) . iterate (map tail) $ xs
これは、すべてのサブリストが同じ長さ (または少なくとも最初のリストが最も短い) であることを前提としていますが、これは のテストを微調整することで簡単に修正できますtakeWhile
。
mirr xs = map (map head) . takeWhile (all (not.null)) . iterate (map tail) $ xs