[Haskell-cafe] Using GHC.Generics to print data type structure
Sjoerd Visscher
sjoerd at w3future.com
Sun Apr 13 13:36:06 UTC 2014
Make the match on (x :*: y) irrefutable:
gprintDT ~(x :*: y) = …
Sjoerd
On 13 Apr 2014, at 15:22, J. Stutterheim <j.stutterheim at me.com> wrote:
> Hi all,
>
> I'm trying to use GHC.Generics to print a data type's structure. I have a test type TestRecord:
>
> data TestRecord = TestRecord
> { trId :: Int
> , someStr :: String }
> deriving Generic
>
> And a PrintDT class:
>
> class PrintDT a where
> printDT :: a -> String
>
> default printDT :: (Generic a, GPrintDT (Rep a)) => a -> String
> printDT = gprintDT . from
>
> With a corresponding instance for TestRecord. The GPrintDT class and instances are defined as follows:
>
> class GPrintDT f where
> gprintDT :: f a -> String
>
> instance (GPrintDT a, GPrintDT b) => GPrintDT (a :*: b) where
> gprintDT (x :*: y) = " { " ++ gprintDT x ++ ", " ++ gprintDT y ++ " }"
>
> instance (Datatype d, GPrintDT f) => GPrintDT (D1 d f) where
> gprintDT d = "data " ++ datatypeName d ++ " = " ++ (gprintDT $ unM1 d)
>
> instance (Constructor c, GPrintDT f) => GPrintDT (C1 c f) where
> gprintDT con
> | conIsRecord con = conName con ++ (gprintDT $ unM1 con)
> | otherwise = "No record"
>
> instance (Selector s, GPrintDT a) => GPrintDT (S1 s a) where
> gprintDT m = selName m
>
> instance (PrintDT a) => GPrintDT (K1 i a) where
> gprintDT _ = ""
>
> instance PrintDT Int where
> printDT n = show n
>
> instance PrintDT String where
> printDT xs = xs
>
> In a first attempt, I apply printDT to a TestRecord value:
>
> test1 :: String
> test1 = printDT (TestRecord 1 "foo")
>
> This prints the expected result:
>
> "data TestRecord = TestRecord { trId, someStr }"
>
> Now ideally, I wouldn't have to specify some value of TestRecord to get this output, since so far, I'm only printing the structure of the TestRecord type, not the values. I would want the following to give me the same result string:
>
> test2 :: String
> test2 = printDT (undefined :: TestRecord)
>
> With the current implementation, test2 gives me the following output:
>
> "data TestRecord = TestRecord*** Exception: Prelude.undefined
>
> Is there a way to implement GPrintDT such that test2 gives me the same output as test1?
>
> Thanks!
>
> - Jurriën
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
More information about the Haskell-Cafe
mailing list