tuplas - Formato de salida de lista en Haskell?
multiplicar haskell (3)
¿Algo como esto?
import Data.List (intercalate)
data Foo = Foo String String [Int]
fooToLine :: Foo -> String
fooToLine (Foo a b cs) = a ++ " | " ++ b ++ " | " ++ intercalate ", " (map show cs)
Ahora, puedes hacer
>>> fooToLine (Foo "Hello" "World" [1, 2, 3])
"Hello | World | 1, 2, 3"
Tengo problemas para tratar de formatear el resultado de una lista de mi propio tipo en Haskell.
Me gustaría algo como esto:
Make | Model | Years(this is a list) <- this would be the headers if you like
-------------------
Item1 | Item1 | Item1s,Item1s
Item2 | Item2 | Item2s,Items2,Items2
^ Este sería el dato cargado desde mi tipo String String [Int].
¿Cómo haría esto en Haskell?
En general, usamos bibliotecas de "impresión bonita" para hacer un buen resultado formateado. El estándar que debes saber es Text.PrettyPrint . Dado un tipo de datos, puede caminar de ese tipo, creando un documento bien formateado.
Un ejemplo:
import Text.PrettyPrint
import Data.List
-- a type for records
data T = T { make :: String
, model :: String
, years :: [Int] }
deriving Show
-- test data
test =
[ T "foo" "avenger" [1990, 1992]
, T "bar" "eagle" [1980, 1982]
]
-- print lists of records: a header, then each row
draw :: [T] -> Doc
draw xs =
text "Make/t|/tModel/t|/tYear"
$+$
vcat (map row xs)
where
-- print a row
row t = foldl1 (<|>) [ text (make t)
, text (model t)
, foldl1 (<^>) (map int (years t))
]
-- helpers
x <|> y = x <> text "/t|/t" <> y
x <^> y = x <> text "," <+> y
Pruebas:
main = putStrLn (render (draw test))
Resultados en:
Make | Model | Year
foo | avenger | 1990, 1992
bar | eagle | 1980, 1982
La capacidad de escribir rápidamente impresoras bonitas es una habilidad increíblemente útil.
Aquí hay un generador de tablas generalizado. Calcula el ancho de las columnas para ajustarse a la fila más ancha. El tipo ColDesc
permite especificar, para cada columna, la alineación del título, la cadena de título, la alineación de datos y una función para formatear los datos.
import Data.List (transpose, intercalate)
-- a type for records
data T = T { make :: String
, model :: String
, years :: [Int] }
deriving Show
-- a type for fill functions
type Filler = Int -> String -> String
-- a type for describing table columns
data ColDesc t = ColDesc { colTitleFill :: Filler
, colTitle :: String
, colValueFill :: Filler
, colValue :: t -> String
}
-- test data
test =
[ T "foo" "avenger" [1990, 1992]
, T "bar" "eagle" [1980, 1982, 1983]
]
-- functions that fill a string (s) to a given width (n) by adding pad
-- character (c) to align left, right, or center
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
-- functions that fill with spaces
left = fillLeft '' ''
right = fillRight '' ''
center = fillCenter '' ''
-- converts a list of items into a table according to a list
-- of column descriptors
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
Corriendo:
putStrLn $ showTable [ ColDesc center "Make" left make
, ColDesc center "Model" left model
, ColDesc center "Year" right (intercalate ", " . map show . years)
] test
Resultados en:
Make | Model | Year
-----+---------+-----------------
foo | avenger | 1990, 1992
bar | eagle | 1980, 1982, 1983