Having the following record:
data Sleep = Sleep
{ _duration :: Maybe Int
, _drunk :: Bool
}
Is there a way to do the following:
deriveSomething ''Sleep
fieldName duration :: String -- "duration"
I need this for typesafe DB specific field updates, i.e:
setField connection key duration (Just 50)
It needs to be DB-agnostic though (thus opaleye etc. is out).
(If this can be achieved with a standard package like lens even better, but I wasn't able to find anything.)
You can do this using Data.Data:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
data Sleep = Sleep
{ _duration :: Maybe Int
, _drunk :: Bool
} deriving (Typeable, Data)
fieldNames :: Data a => a -> [String]
fieldNames = constrFields . toConstr
Example:
> fieldNames (Sleep undefined undefined)
["_duration", "_drunk"]
You'll have to decide how you want to transform the names to database columns after that, but that should be fairly easy.
This requires a value created using a particular constructor, remember that data types can have many constructors. There isn't really a way around this, but you could have something like
sleepFieldNames :: [String]
sleepFieldNames = fieldNames (Sleep undefined undefined)
So that you don't have to keep recalculating it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With