在Haskell中显示矩阵的实例

时间:2017-05-27 11:32:27

标签: haskell matrix

我一直在尝试创建一个show实例,以便可视化给定的矩阵,并创建一个包含矩阵之间和列之间的列的轮廓。到目前为止我设法完成的是:

data Mat a = Mat [[a]]
instance (Show a) => Show (Mat a) where
show (Mat x) = "\n" ++ " ---\n"++unlines ( map (\r -> showRow r ++ "\n ---") x ) ++ "\n"
    where
      showRow list = "¦ "++unwords ( map (\v -> show v ++" ¦") list)

假设我们想要测试矩阵Mat [[1,2,3],[4,5,6]]

命令行的输出如下:

 ---
¦ 1 ¦ 2 ¦ 3 ¦
 ---
¦ 4 ¦ 5 ¦ 6 ¦
 ---

我想要实现的是使用每列其余部分上方的水平线格式化给定矩阵,如下所示:

 --- --- ---
¦ 1 ¦ 2 ¦ 3 ¦
 --- --- ---
¦ 4 ¦ 5 ¦ 6 ¦
 --- --- ---

1 个答案:

答案 0 :(得分:0)

如果您假设矩阵的所有行具有相同的列数(或者至少任何矩阵的第一行至少具有与任何其他矩阵一样多的列),并且三个破折号足以作为边界对于任何单元格,您可以通过获取前导行的length来计算行之间使用的短划线数。

如果这些假设不成立,则需要对数组进行一次传递以计算任何行的最大宽度,然后进行第二次传递以绘制矩阵。如果矩阵可以包含[0..9]范围之外的数字,则还需要计算每列的宽度。

算法可能是:

  1. 将矩阵中的每个数字映射到String,生成[[String]]
  2. 生成列宽列表,其元素是该列中任何行元素的最大宽度。
  3. 左键填充[[String]]中的每个字符串,其列宽为空格。
  4. 连接每一行的列,在元素和相应的左右边框之间添加适当的分隔符。结果是[String],其元素是每行的图形表示。
  5. 如果您希望在行上方,下方或行之间添加水平规则,请取[String]的任何元素的长度(因为所有列现在都填充到其最大宽度,所有行现在应该具有相同的长度。)并生成该数量的框图字符,例如ASCII "---"或Unicode "┌─┬─┐"
  6. 将行和分隔符行连接到由换行符分隔的String
  7. 正如Rein Henrichs在评论中提到的那样,您可以考虑将此函数命名为show以外的其他函数。