packages feed

records-edsl-core-0.1.0: Records/EDSL/Deriving/HasField.hs

module Records.EDSL.Deriving.HasField where

import Data.Proxy
import GHC.Records qualified as GHC
import Language.Haskell.TH qualified as TH
import Records.EDSL.Deriving.Type
import Records.EDSL.Description
import Relude

deriveHasFields :: Deriver
deriveHasFields = deriver #ghc_HasField \RecordDesc {typeName, fields} ->
  concat <$> forM fields \FieldDesc {name, nameText, type_} ->
    if toText (TH.nameBase name) == nameText
      then pure []
      else
        [d|
          instance GHC.HasField $(TH.litT (TH.strTyLit (toString nameText))) $(TH.conT typeName) $(pure type_.hask.type_) where
            getField = getFieldP (Proxy :: Proxy $(TH.litT (TH.strTyLit (TH.nameBase name))))
              where
                getFieldP :: forall x r a. (GHC.HasField x r a) => Proxy x -> r -> a
                getFieldP _ = GHC.getField @x
          |]