heidi icon indicating copy to clipboard operation
heidi copied to clipboard

pretty printing/ASCII visualization of encoded rows

Open ocramz opened this issue 6 years ago • 3 comments

e.g. ascii :

+-------------+-----------------+
| Person      | House           |
+-------+-----+-------+---------+
| Name  | Age | Color | Price   |
+-------+-----+-------+---------+
| David | 63  | Green | $170000 |
| Ava   | 34  | Blue  | $115000 |
| Sonia | 12  | Green | $150000 |
+-------+-----+-------+---------+

https://hackage.haskell.org/package/colonnade-1.2.0.1/docs/Colonnade.html#g:10

ocramz avatar May 05 '19 04:05 ocramz

generate CSV header from the type with generics-sop metadata

ocramz avatar Oct 08 '20 20:10 ocramz

After a fair bit of trial and error, header produces a simple representation of an arbitrary type which can be pretty-printed as a tree :

data A = MkA Int deriving (Eq, Show, G.Generic, Heidi)
data B = MkB Int Char deriving (Eq, Show, G.Generic, Heidi)
data B2 = MkB2 { b21 :: Int, b22 :: Char } deriving (Eq, Show, G.Generic, Heidi)
data C = MkC1 {c1 :: Int} | MkC2 A | MkC3 () deriving (Eq, Show, G.Generic, Heidi)
data R = MkR { r1 :: B2, r2 :: C , r3 :: B } deriving (Eq, Show, G.Generic, Heidi)
λ> printBox $ headerBox $ header (Proxy @R)
                       R                        
------------------------------------------------
                      MkR                       
                       R                        
------------*------------*----------------------
     r1     |     r3     |          r2          
     B2           B                 C           
 ----------   ----------   ------+------+------ 
    MkB2         MkB        MkC3 | MkC1 | MkC2  
     B2           B          ()    Int     A    
 ----*-----   ----*-----                  ---   
 b21 | b22     _0 |  _1                   MkA   
 Int   Char   Int   Char                  Int   

ocramz avatar Oct 19 '20 16:10 ocramz

In case someone else wants to move this forward, my thinking so far is as follows:

  • [x] header computes a rose tree representation of a type, and only requires a Generic and an empty instance of HasHeader (populated automatically via the Generic instance) (see https://github.com/ocramz/heidi/blob/master/src/Core/Data/Frame/PrettyPrint.hs#L152 )
  • [x] similarly, encode uses the generic representation of a value and produces a corresponding representation; values however (i.e. data rows) are "flattened" from rose trees into one-level deep tries, keyed by lists of elements (https://github.com/ocramz/heidi/blob/master/src/Data/Generics/Encode/Internal.hs#L101). This flat representation makes lookup and traversal convenient. A heidi dataframe is produced by encodeing all values in a list.
  • [x] the rose trees produced by header are convenient for pretty-printing the sum-of-products structure of general Haskell ADTs, as seen above (implementation at https://github.com/ocramz/heidi/blob/master/src/Core/Data/Frame/PrettyPrint.hs#L91 )
  • [ ] additionally, the trees produced by header contain all possible combination of keys that might appear in encoded values, which is why Header values can be used in the Show instance of an encoded dataframe:
    • [ ] take few rows (e.g. 10) for each value, perform lookup using the Header keys and render in the corresponding column, under the header

ocramz avatar Oct 19 '20 20:10 ocramz