packages feed

overloaded-records 0.1.0.0 → 0.2.0.0

raw patch · 4 files changed

+357/−72 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.OverloadedRecords.TH: defaultMakeAccessorName :: String -> String -> Word -> Maybe String -> Maybe String
- Data.OverloadedRecords.TH: makeAccessorName :: Functor f => (MakeAccessorName -> f MakeAccessorName) -> DeriveOverloadedRecordsParams -> f DeriveOverloadedRecordsParams
- Data.OverloadedRecords.TH: type MakeAccessorName = String -> String -> Word -> Maybe String -> Maybe String
+ Data.OverloadedRecords.TH: GetterAndSetterField :: String -> (Maybe (ExpQ, ExpQ)) -> OverloadedField
+ Data.OverloadedRecords.TH: GetterOnlyField :: String -> (Maybe ExpQ) -> OverloadedField
+ Data.OverloadedRecords.TH: data OverloadedField
+ Data.OverloadedRecords.TH: defaultFieldDerivation :: FieldDerivation
+ Data.OverloadedRecords.TH: defaultMakeFieldName :: String -> String -> Word -> Maybe String -> Maybe String
+ Data.OverloadedRecords.TH: field :: String -> TypeQ -> TypeQ -> TypeQ -> TypeQ -> ExpQ -> ExpQ -> DecsQ
+ Data.OverloadedRecords.TH: fieldDerivation :: IsLabel "fieldDerivation" a => a
+ Data.OverloadedRecords.TH: fieldGetter :: String -> TypeQ -> TypeQ -> ExpQ -> DecsQ
+ Data.OverloadedRecords.TH: fieldSetter :: String -> TypeQ -> TypeQ -> TypeQ -> TypeQ -> ExpQ -> DecsQ
+ Data.OverloadedRecords.TH: instance Data.OverloadedRecords.HasField "fieldDerivation" Data.OverloadedRecords.TH.DeriveOverloadedRecordsParams Data.OverloadedRecords.TH.FieldDerivation
+ Data.OverloadedRecords.TH: instance Data.OverloadedRecords.SetField "fieldDerivation" Data.OverloadedRecords.TH.DeriveOverloadedRecordsParams Data.OverloadedRecords.TH.FieldDerivation
+ Data.OverloadedRecords.TH: instance GHC.Generics.Constructor Data.OverloadedRecords.TH.C1_0OverloadedField
+ Data.OverloadedRecords.TH: instance GHC.Generics.Constructor Data.OverloadedRecords.TH.C1_1OverloadedField
+ Data.OverloadedRecords.TH: instance GHC.Generics.Datatype Data.OverloadedRecords.TH.D1OverloadedField
+ Data.OverloadedRecords.TH: instance GHC.Generics.Generic Data.OverloadedRecords.TH.OverloadedField
+ Data.OverloadedRecords.TH: overloadedRecord :: DeriveOverloadedRecordsParams -> Name -> DecsQ
+ Data.OverloadedRecords.TH: overloadedRecordFor :: Name -> (DeriveOverloadedRecordsParams -> DeriveOverloadedRecordsParams) -> DecsQ
+ Data.OverloadedRecords.TH: overloadedRecordsFor :: [Name] -> (DeriveOverloadedRecordsParams -> DeriveOverloadedRecordsParams) -> DecsQ
+ Data.OverloadedRecords.TH: simpleField :: String -> TypeQ -> TypeQ -> ExpQ -> ExpQ -> DecsQ
+ Data.OverloadedRecords.TH: simpleFieldSetter :: String -> TypeQ -> TypeQ -> ExpQ -> DecsQ
+ Data.OverloadedRecords.TH: type FieldDerivation = String Name of the type, of which this field is part of. -> String Name of the constructor, of which this field is part of. -> Word Field position as an argument of the constructor it is part of. Indexing starts from zero. -> Maybe String Name of the field (record) accessor; 'Nothing' means that there is no record accessor defined for it. -> Maybe OverloadedField Describes how overloaded record field should be generated for this specific constructor field. 'Nothing' means that no overloaded record field should be derived. See also 'OverloadedField' for details.
- Data.OverloadedRecords.TH: overloadedRecords :: DeriveOverloadedRecordsParams -> Name -> DecsQ
+ Data.OverloadedRecords.TH: overloadedRecords :: DeriveOverloadedRecordsParams -> [Name] -> DecsQ

Files

ChangeLog.md view
@@ -1,6 +1,21 @@ # ChangeLog / ReleaseNotes  +## Version 0.2.0.0++* Function `overloadedRecords` renamed to `overloadedRecord`. There is also new+  `overloadedRecords` function, that behaves as `overloadedRecord`, but for+  multiple types at once. (**breaking change**)+* It is now possible to customize overloadedRecord\* family of functions with+  custom getter and setter implementation. (**new**)+* Types and functions follow, hopefully, better naming conventions. (**change**)+* More low-level template haskell functions for those cases when it is+  necessary to build your own higher-level ones, or when you need much more+  control over the result. (**new**)+* Uploaded to [Hackage][]:+  <http://hackage.haskell.org/package/overloaded-records-0.2.0.0>++ ## Version 0.1.0.0  * First public release.
README.md view
@@ -10,8 +10,45 @@  ## Description -Implementation of /Overloaded Records/ based on current GHC proposal.+Implementation of *Overloaded Record Fields* based on current GHC proposal. It+is built on top of functionality that is included in GHC 8.0.1, but it works on+older GHC versions as well. Most importantly, this library provides Template+Haskell functions for automatic deriving of instancess for `HasField` and+`SetField` type classes. With these instances overloaded fields can be used+directly as getters and lenses. +```Haskell+import Data.OverloadedRecords.TH (overloadedRecord)++newtype Bar a = Bar {_bar :: a}++overloadedRecord def ''Bar+```++On GHC 8.0.1 it is possible to just write:++```Haskell+{-# LANGUAGE OverloadedLabels #-}++import Control.Lens ((+~))++add :: Int -> Bar Int -> Bar Int+add n = #bar +~ n+```++For older GHC versions there is a family of Template Haskell functions that+will derive overloaded labels in form of standard haskell definitions:++```Haskell+import Control.Lens ((+~))+import Data.OverloadedLabels.TH (label)++label "bar"++add :: Int -> Bar Int -> Bar Int+add n = bar +~ n+```+ This implementation is highly experimental and may change rapidly.  More about the current status of OverloadedRecordFields language extension can@@ -21,18 +58,18 @@ ## Usage Example  ```Haskell-{-# LANGUAGE DataKinds #-}              -- overloadedRecords, labels+{-# LANGUAGE DataKinds #-}              -- overloadedRecord, labels {-# LANGUAGE FlexibleContexts #-}       -- labels-{-# LANGUAGE FlexibleInstances #-}      -- overloadedRecords-{-# LANGUAGE MultiParamTypeClasses #-}  -- overloadedRecords-{-# LANGUAGE TemplateHaskell #-}        -- overloadedRecords, labels-{-# LANGUAGE TypeFamilies #-}           -- overloadedRecords+{-# LANGUAGE FlexibleInstances #-}      -- overloadedRecord+{-# LANGUAGE MultiParamTypeClasses #-}  -- overloadedRecord+{-# LANGUAGE TemplateHaskell #-}        -- overloadedRecord, labels+{-# LANGUAGE TypeFamilies #-}           -- overloadedRecord module FooBar   where  import Data.Default.Class (Default(def)) -import Data.OverloadedRecords.TH (overloadedRecords)+import Data.OverloadedRecords.TH (overloadedRecord) import Data.OverloadedLabels.TH (label, labels)  @@ -41,12 +78,12 @@     , _y :: a     } -overloadedRecords def ''Foo+overloadedRecord def ''Foo labels ["x", "y"]  newtype Bar a = Bar {_bar :: a} -overloadedRecords def ''Bar+overloadedRecord def ''Bar label "bar" ``` 
overloaded-records.cabal view
@@ -1,16 +1,21 @@ name:                   overloaded-records-version:                0.1.0.0+version:                0.2.0.0 synopsis:               Overloaded Records based on current GHC proposal. description:-  Implementation of /Overloaded Records/ based on current GHC proposal.+  Implementation of /Overloaded Record Fields/ based on current GHC proposal.+  It is built on top of functionality that is included in GHC 8.0.1, but it+  works on older GHC versions as well. Most importantly, this library provides+  Template Haskell functions for automatic deriving of instancess for+  @HasField@ and @SetField@ type classes. With these instances overloaded+  fields can be used directly as getters and lenses.   .+  See README for usage examples.+  .   This implementation is highly experimental and may change rapidly.   .   More about the current status of OverloadedRecordFields language extension   can be found on:   <https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields GHC Wiki: OverloadedRecordFields>.-  .-  See README for usage example.  homepage:               https://github.com/trskop/overloaded-records bug-reports:            https://github.com/trskop/overloaded-records/issues@@ -84,4 +89,4 @@ source-repository this   type:                 git   location:             git://github.com/trskop/overloaded-records.git-  tag:                  0.1.0.0+  tag:                  0.2.0.0
src/Data/OverloadedRecords/TH.hs view
@@ -1,12 +1,22 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeSynonymInstances #-} +#ifndef HAVE_OVERLOADED_LABELS+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MagicHash #-}+#endif+ #if 0 #if HAVE_MONAD_FAIL && MIN_VERSION_template_haskell(2,11,0) #define _FAIL_IN_MONAD@@ -26,19 +36,37 @@ -- -- Maintainer:   peter.trsko@gmail.com -- Stability:    experimental--- Portability:  CPP, DeriveDataTypeable, DeriveGeneric, LambdaCase,---               NoImplicitPrelude, RecordWildCards, TemplateHaskell,---               TupleSections+-- Portability:  CPP, DataKinds, DeriveDataTypeable, DeriveGeneric,+--               FlexibleContexts (GHC <8), FlexibleInstances, LambdaCase,+--               MagicHash (GHC <8), MultiParamTypeClasses, NoImplicitPrelude,+--               RecordWildCards, TemplateHaskell, TupleSections, TypeFamilies,+--               TypeSynonymInstances -- -- Derive magic instances for OverloadedRecordFields. module Data.OverloadedRecords.TH     (     -- * Derive OverloadedRecordFields instances-      overloadedRecords+      overloadedRecord+    , overloadedRecords+    , overloadedRecordFor+    , overloadedRecordsFor++    -- ** Customize Derivation Process     , DeriveOverloadedRecordsParams-    , MakeAccessorName-    , makeAccessorName-    , defaultMakeAccessorName+#ifndef HAVE_OVERLOADED_LABELS+    , fieldDerivation+#endif+    , FieldDerivation+    , OverloadedField(..)+    , defaultFieldDerivation+    , defaultMakeFieldName++    -- * Low-level Deriving Mechanism+    , field+    , simpleField+    , fieldGetter+    , fieldSetter+    , simpleFieldSetter     )   where @@ -64,13 +92,16 @@     , replicate     , zip     )-import Data.Maybe (Maybe(Just, Nothing))+import Data.Maybe (Maybe(Just, Nothing), fromMaybe) import Data.Monoid ((<>)) import Data.String (String)-import Data.Traversable (forM)+import Data.Traversable (forM, mapM) import Data.Typeable (Typeable) import Data.Word (Word) import GHC.Generics (Generic)+#ifndef HAVE_OVERLOADED_LABELS+import GHC.Exts (Proxy#, proxy#)+#endif import Text.Show (Show(show))  import Language.Haskell.TH@@ -107,6 +138,9 @@  import Data.Default.Class (Default(def)) +#ifndef HAVE_OVERLOADED_LABELS+import Data.OverloadedLabels (IsLabel(fromLabel))+#endif import Data.OverloadedRecords     ( FieldType     , HasField(getField)@@ -115,54 +149,86 @@     )  --- Parameters for customization of deriving process. Use 'def' to get+#ifndef HAVE_OVERLOADED_LABELS+-- | Overloaded label that can be used for accessing function of type+-- 'FieldDerivation' from 'DeriveOverloadedRecordsParams'.+fieldDerivation :: IsLabel "fieldDerivation" a => a+fieldDerivation = fromLabel (proxy# :: Proxy# "fieldDerivation")+#endif++-- | Parameters for customization of deriving process. Use 'def' to get -- default behaviour. data DeriveOverloadedRecordsParams = DeriveOverloadedRecordsParams-    { _strictAccessors :: Bool+    { _strictFields :: Bool     -- ^ Make setter and getter strict. **Currently unused.**-    , _makeAccessorName :: MakeAccessorName-    -- ^ See 'MakeAccessorName' for description.+    , _fieldDerivation :: FieldDerivation+    -- ^ See 'FieldDerivation' for description.     }   deriving (Generic, Typeable) --- | Pseudo type definition:------ @--- :: TypeName--- -> ConstructorName--- -> FieldIndex--- -> Maybe AccessorName--- -> Maybe OverloadedLabelName--- @+type instance FieldType "fieldDerivation" DeriveOverloadedRecordsParams =+    FieldDerivation++instance+    HasField "fieldDerivation" DeriveOverloadedRecordsParams FieldDerivation+  where+    getField _proxy = _fieldDerivation++type instance+    UpdateType "fieldDerivation" DeriveOverloadedRecordsParams FieldDerivation =+        DeriveOverloadedRecordsParams++instance+    SetField "fieldDerivation" DeriveOverloadedRecordsParams FieldDerivation+  where+    setField _proxy s b = s{_fieldDerivation = b}++-- | Describes what should be the name of overloaded record field, and can also+-- provide custom implementation of getter and setter.+data OverloadedField+    = GetterOnlyField String (Maybe ExpQ)+    -- ^ Derive only getter instances. If second argument is 'Just', then it+    -- contains custom definition of getter function.+    | GetterAndSetterField String (Maybe (ExpQ, ExpQ))+    -- ^ Derive only getter instances. If second argument is 'Just', then it+    -- contains custom definitions of getter and setter functions,+    -- respectively.+  deriving (Generic, Typeable)++-- | Type signature of a function that can customize the derivation of each+-- individual overloaded record field. ----- If field has an accessor then the function will get its name or 'Nothing'+-- If field has an selector then the function will get its name or 'Nothing' -- otherwise.  Function has to return 'Nothing' in case when generating -- overloaded record field instances is not desired.------ @FieldIndex@ is starting from zero.-type MakeAccessorName =-    String -> String -> Word -> Maybe String -> Maybe String---- | Lens for accessing function that specifies what magic instances will be--- defined and what will be the names of overloaded record fields.-makeAccessorName-    :: Functor f-    => (MakeAccessorName -> f MakeAccessorName)-    -> DeriveOverloadedRecordsParams -> f DeriveOverloadedRecordsParams-makeAccessorName f s@DeriveOverloadedRecordsParams{_makeAccessorName = a} =-    (\b -> s{_makeAccessorName = b}) <$> f a+type FieldDerivation+    =  String+    -- ^ Name of the type, of which this field is part of.+    -> String+    -- ^ Name of the constructor, of which this field is part of.+    -> Word+    -- ^ Field position as an argument of the constructor it is part of.+    -- Indexing starts from zero.+    -> Maybe String+    -- ^ Name of the field (record) accessor; 'Nothing' means that there is no+    -- record accessor defined for it.+    -> Maybe OverloadedField+    -- ^ Describes how overloaded record field should be generated for this+    -- specific constructor field. 'Nothing' means that no overloaded record+    -- field should be derived. See also 'OverloadedField' for details.  -- | Suppose we have a weird type definition as this: -- -- @--- data SomeType = SomeConstructor+-- data SomeType a b c = SomeConstructor --     { _fieldX :: a --     , someTypeFieldY :: b --     , someConstructorFieldZ :: c+--     , anythingElse :: (a, b, c) --     } -- @ ----- Then for each of those fields, 'defaultMakeAccessorName' will produce+-- Then for each of those fields, 'defaultMakeFieldName' will produce -- expected OverloadedLabel name: -- -- * @_fieldX --> fieldX@@@ -171,27 +237,29 @@ -- -- * @someConstructorFieldZ --> fieldZ@ ----- Any other field name is kept unchanged.-defaultMakeAccessorName+-- * @anythingElse@ is ignored+defaultMakeFieldName     :: String     -- ^ Name of the type, of which this field is part of.     -> String     -- ^ Name of the constructor, of which this field is part of.     -> Word     -- ^ Field position as an argument of the constructor it is part of.+    -- Indexing starts from zero.     -> Maybe String     -- ^ Name of the field (record) accessor; 'Nothing' means that there is no     -- record accessor defined for it.     -> Maybe String-    -- ^ Overloaded label name for the field; 'Nothing' means that there-    -- shouldn't be a label associated with it.-defaultMakeAccessorName typeName constructorName _fieldPosition = \case+    -- ^ Overloaded record field name to be used for this specific constructor+    -- field; 'Nothing' means that there shouldn't be a label associated with+    -- it.+defaultMakeFieldName typeName constructorName _fieldPosition = \case     Nothing -> Nothing     Just fieldName       | startsWith "_"               -> Just $ dropPrefix "_"        fieldName       | startsWith typePrefix        -> Just $ dropPrefix typePrefix fieldName       | startsWith constructorPrefix -> Just $ dropPrefix typePrefix fieldName-      | otherwise                    -> Just fieldName+      | otherwise                    -> Nothing       where         startsWith :: String -> Bool         startsWith = (`List.isPrefixOf` fieldName)@@ -205,28 +273,33 @@         typePrefix = headToLower typeName         constructorPrefix = headToLower constructorName +-- | Function used by default value of 'DeriveOverloadedRecordsParams'.+defaultFieldDerivation :: FieldDerivation+defaultFieldDerivation =+    (((fmap (`GetterAndSetterField` Nothing) .) .) .) . defaultMakeFieldName+ -- | -- @ -- 'def' = 'DeriveOverloadedRecordsParams'---     { strictAccessors = 'False'---     , 'makeAccessorName' = 'defaultMakeAccessorName'+--     { strictFields = 'False'+--     , 'fieldDerivation' = 'defaultFieldDerivation' --     } -- @ instance Default DeriveOverloadedRecordsParams where     def = DeriveOverloadedRecordsParams-        { _strictAccessors = False-        , _makeAccessorName = defaultMakeAccessorName+        { _strictFields = False+        , _fieldDerivation = defaultFieldDerivation         } --- | Derive magic OverloadedRecordFields instances for specified type name.-overloadedRecords+-- | Derive magic OverloadedRecordFields instances for specified type.+overloadedRecord     :: DeriveOverloadedRecordsParams     -- ^ Parameters for customization of deriving process. Use 'def' to get     -- default behaviour.     -> Name     -- ^ Name of the type for which magic instances should be derived.     -> DecsQ-overloadedRecords params = withReified $ \name -> \case+overloadedRecord params = withReified $ \name -> \case     TyConI dec -> case dec of         -- Not supporting DatatypeContexts, hence the [] required as the first         -- argument to NewtypeD and DataD.@@ -257,6 +330,55 @@     errMessage n x =         "`" <> show n <> "' is neither newtype nor data type: " <> show x +-- | Derive magic OverloadedRecordFields instances for specified types.+overloadedRecords+    :: DeriveOverloadedRecordsParams+    -- ^ Parameters for customization of deriving process. Use 'def' to get+    -- default behaviour.+    -> [Name]+    -- ^ Names of the types for which magic instances should be derived.+    -> DecsQ+overloadedRecords params = fmap concat . mapM (overloadedRecord params)++-- | Derive magic OverloadedRecordFields instances for specified type.+--+-- Similar to 'overloadedRecords', but instead of+-- 'DeriveOverloadedRecordsParams' value it takes function which can modify its+-- default value.+--+-- @+-- data Coordinates2D a+--     { coordinateX :: a+--     , coordinateY :: a+--     }+--+-- 'overloadedRecordsFor' ''Coordinates2D+--     $ \#fieldDerivation .~ \\_ _ _ -> \\case+--         Nothing -> Nothing+--         Just field -> lookup field+--            [ (\"coordinateX\", 'GetterOnlyField' \"x\" Nothing)+--            , (\"coordinateY\", 'GetterOnlyField' \"y\" Nothing)+--            ]+-- @+overloadedRecordFor+    :: Name+    -- ^ Name of the type for which magic instances should be derived.+    -> (DeriveOverloadedRecordsParams -> DeriveOverloadedRecordsParams)+    -- ^ Function that modifies parameters for customization of deriving+    -- process.+    -> DecsQ+overloadedRecordFor typeName f = overloadedRecord (f def) typeName++-- | Derive magic OverloadedRecordFields instances for specified types.+overloadedRecordsFor+    :: [Name]+    -- ^ Names of the types for which magic instances should be derived.+    -> (DeriveOverloadedRecordsParams -> DeriveOverloadedRecordsParams)+    -- ^ Function that modifies parameters for customization of deriving+    -- process.+    -> DecsQ+overloadedRecordsFor typeNames f = overloadedRecords (f def) typeNames+ -- | Derive magic instances for all fields of a specific data constructor of a -- specific type. deriveForConstructor@@ -280,6 +402,13 @@         deriveFor constructorName [arg0, arg1] $ \(strict, argType) f ->             f Nothing strict argType +#if 0+#if MIN_VERSION_template_haskell(2,11,0)+    GadtC _ _ _ ->+    RecGadtC _ _ _ ->+#endif+#endif+     -- Existentials aren't supported.     ForallC _typeVariables _context _constructor -> return []   where@@ -343,16 +472,29 @@ deriveForField params DeriveFieldParams{..} =     case possiblyLabel of         Nothing -> return []-        Just label -> (<>)-            <$> deriveGetter labelType recordType (return fieldType) getterExpr-            <*> deriveSetter labelType recordType (return fieldType) newRecordType-                    newFieldType setterExpr+        Just (GetterOnlyField label customGetterExpr) ->+            deriveGetter' (strTyLitT label)+                $ fromMaybe derivedGetterExpr customGetterExpr+        Just (GetterAndSetterField label customGetterAndSetterExpr) -> (<>)+            <$> deriveGetter' labelType getterExpr+            <*> deriveSetter' labelType setterExpr           where             labelType = strTyLitT label++            (getterExpr, setterExpr) =+                fromMaybe (derivedGetterExpr, derivedSetterExpr)+                    customGetterAndSetterExpr   where-    possiblyLabel = _makeAccessorName params (nameBase typeName)+    possiblyLabel = _fieldDerivation params (nameBase typeName)         (nameBase constructorName) currentIndex (fmap nameBase accessorName) +    deriveGetter' labelType =+        deriveGetter labelType recordType (return fieldType)++    deriveSetter' labelType =+        deriveSetter labelType recordType (return fieldType) newRecordType+            newFieldType+     recordType = foldl appT (conT typeName) $ List.map varT typeVariables      -- TODO: When field type is polymorphic, then we should allow to change it.@@ -366,7 +508,7 @@     inbetween :: (a -> [b]) -> a -> a -> b -> [b]     inbetween f a1 a2 b = f a1 <> (b : f a2) -    getterExpr = case accessorName of+    derivedGetterExpr = case accessorName of         Just name -> varE name         Nothing -> do             a <- newName "a"@@ -376,7 +518,7 @@         nthArg :: Pat -> [Pat]         nthArg = inbetween wildPs currentIndex numVarsOnRight -    setterExpr = case accessorName of+    derivedSetterExpr = case accessorName of         Just name -> do             s <- newName "s"             b <- newName "b"@@ -397,6 +539,59 @@             constrExpression before b after = foldl appE (conE constructorName)                 $ varEs before <> (b : varEs after) +-- | Derive instances for overloaded record field, both getter and setter.+field+    :: String+    -- ^ Overloaded label name.+    -> TypeQ+    -- ^ Record type.+    -> TypeQ+    -- ^ Field type.+    -> TypeQ+    -- ^ Record type after update.+    -> TypeQ+    -- ^ Setter will set field to a value of this type.+    -> ExpQ+    -- ^ Getter function.+    -> ExpQ+    -- ^ Setter function.+    -> DecsQ+field label recType fldType newRecType newFldType getterExpr setterExpr = (<>)+    <$> deriveGetter labelType recType fldType getterExpr+    <*> deriveSetter labelType recType fldType newRecType newFldType setterExpr+  where+    labelType = strTyLitT label++-- | Derive instances for overloaded record field, both getter and setter. Same+-- as 'field', but record type is the same before and after update and so is+-- the field type.+simpleField+    :: String+    -- ^ Overloaded label name.+    -> TypeQ+    -- ^ Record type.+    -> TypeQ+    -- ^ Field type.+    -> ExpQ+    -- ^ Getter function.+    -> ExpQ+    -- ^ Setter function.+    -> DecsQ+simpleField label recType fldType = field label recType fldType recType fldType++-- | Derive instances for overloaded record field getter.+fieldGetter+    :: String+    -- ^ Overloaded label name.+    -> TypeQ+    -- ^ Record type.+    -> TypeQ+    -- ^ Field type+    -> ExpQ+    -- ^ Getter function.+    -> DecsQ+fieldGetter = deriveGetter . strTyLitT+ -- | Derive only getter related instances. deriveGetter :: TypeQ -> TypeQ -> TypeQ -> ExpQ -> DecsQ deriveGetter labelType recordType fieldType getter =@@ -405,6 +600,39 @@         instance HasField $(labelType) $(recordType) $(fieldType) where             getField _proxy = $(getter)     |]++-- | Derive instances for overloaded record field setter. Same as+-- 'fieldSetter', but record type is the same before and after update and so is+-- the field type.+simpleFieldSetter+    :: String+    -- ^ Overloaded label name.+    -> TypeQ+    -- ^ Record type.+    -> TypeQ+    -- ^ Field type.+    -> ExpQ+    -- ^ Setter function.+    -> DecsQ+simpleFieldSetter label recordType fieldType =+    fieldSetter label recordType fieldType recordType fieldType++-- | Derive instances for overloaded record field setter.+fieldSetter+    :: String+    -- ^ Overloaded label name.+    -> TypeQ+    -- ^ Record type.+    -> TypeQ+    -- ^ Field type.+    -> TypeQ+    -- ^ Record type after update.+    -> TypeQ+    -- ^ Setter will set field to a value of this type.+    -> ExpQ+    -- ^ Setter function.+    -> DecsQ+fieldSetter = deriveSetter . strTyLitT  -- | Derive only setter related instances. deriveSetter :: TypeQ -> TypeQ -> TypeQ -> TypeQ -> TypeQ -> ExpQ -> DecsQ