这是一个通用的表格生成器。它计算列宽以适应最宽的行。`ColDesc` 类型允许您为每个列指定标题对齐方式、标题字符串、数据对齐方式和格式化数据的函数。
import Data.List (transpose, intercalate)
data T = T { make :: String
, model :: String
, years :: [Int] }
deriving Show
type Filler = Int -> String -> String
data ColDesc t = ColDesc { colTitleFill :: Filler
, colTitle :: String
, colValueFill :: Filler
, colValue :: t -> String
}
test =
[ T "foo" "avenger" [1990, 1992]
, T "bar" "eagle" [1980, 1982, 1983]
]
fillLeft c n s = s ++ replicate (n - length s) c
fillRight c n s = replicate (n - length s) c ++ s
fillCenter c n s = replicate l c ++ s ++ replicate r c
where x = n - length s
l = x `div` 2
r = x - l
left = fillLeft ' '
right = fillRight ' '
center = fillCenter ' '
showTable :: [ColDesc t] -> [t] -> String
showTable cs ts =
let header = map colTitle cs
rows = [[colValue c t | c <- cs] | t <- ts]
widths = [maximum $ map length col | col <- transpose $ header : rows]
separator = intercalate "-+-" [replicate width '-' | width <- widths]
fillCols fill cols = intercalate " | " [fill c width col | (c, width, col) <- zip3 cs widths cols]
in
unlines $ fillCols colTitleFill header : separator : map (fillCols colValueFill) rows
跑步:
putStrLn $ showTable [ ColDesc center "Make" left make
, ColDesc center "Model" left model
, ColDesc center "Year" right (intercalate ", " . map show . years)
] test
结果为:
Make | Model | Year
foo | avenger | 1990, 1992
bar | eagle | 1980, 1982, 1983