18

Say I have the following:

data Rec = Rec {
    alpha :: Int,
    beta  :: Double,
    phi   :: Float 
} 

sample = Rec 1 2.3 4.5

I understand Template Haskell & the reify function can get me the record's field names. That is:

print $(f sample) --> ["alpha", "beta", "phi"]

There is also a claim that this can be done without Template Haskell. Can someone provide an example implementation for this can be accomplished?

  • 1
    You can get the field names without template Haskell too. – augustss Dec 10 '11 at 16:21
  • 1
    @augustss: How? Some `Typable` black magic? Either way, most uses one could put this information to would be a great fit for Template Haskell. –  Dec 10 '11 at 16:22
  • 3
    @delnan You can either use `Data.Data` or you can just derive `Show`, show `sample` and do a little parsing of that string. – augustss Dec 10 '11 at 20:42
  • 2
    I don't see many compelling reasons to actually do this. – Dan Burton Dec 10 '11 at 21:55

1 Answers1

19

It can be done with a Data (most GHC versions) or Generic (7.2.x and up) instance, which GHC can derive for you. Here's an example of how to dump record fields with the Data typeclass:

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Data

data Rec = Rec {
    alpha :: Int,
    beta  :: Double,
    phi   :: Float 
}  deriving (Data, Typeable)

sample = Rec 1 2.3 4.5

main :: IO ()
main = print . constrFields . toConstr $ sample 
Nathan Howell
  • 4,627
  • 1
  • 22
  • 30
  • 10
    You can also avoid having to use an instance of the type (`sample` in this case) by using `print . map constrFields . dataTypeConstrs . dataTypeOf $ (undefined :: Rec)`. This will generate a list of all the fields in all of the available constructors (and can of course be tailored to your liking) – dflemstr Dec 10 '11 at 16:54