Created
September 17, 2024 21:04
-
-
Save someodd/b717a1b9679e631463bd262338b1d932 to your computer and use it in GitHub Desktop.
Haskell: data type with record fields to text pairs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Data (Data, gmapQ, toConstr, cast) | |
import Data.Maybe (catMaybes) | |
import Data.Data (constrFields) | |
import qualified Data.Text as Text | |
{- | Convert any generic data type with record syntax to a list | |
of key-value `Text` pairs. | |
Uses some Haskell magic. | |
-} | |
genericToPairs :: (Data a) => a -> [(Text.Text, Text.Text)] | |
genericToPairs record = catMaybes $ zipWith extractField (map Text.pack fieldNames) fields | |
where | |
-- Get the list of field names from the data type | |
fieldNames = constrFields $ toConstr record | |
fields = gmapQ castToMaybe record | |
-- Attempt to cast each field to `Maybe` | |
castToMaybe :: (Data b) => b -> Maybe (Maybe Text.Text) | |
castToMaybe field = cast field :: Maybe (Maybe Text.Text) | |
-- Safely extract fields of type `Maybe` | |
extractField :: Text.Text -> Maybe (Maybe Text.Text) -> Maybe (Text.Text, Text.Text) | |
extractField name (Just (Just value)) = Just (name, value) | |
extractField _ _ = Nothing |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm using some language extensions that I think may be required to get this to work. And the data types you convert have to derive something like
deriving (Show, Data, Typeable, Generic, FromJSON)
.For example:
Here are the language extensions:
... and: