diff --git a/src/Data/Generic/HKD.hs b/src/Data/Generic/HKD.hs index df72332..3246d12 100644 --- a/src/Data/Generic/HKD.hs +++ b/src/Data/Generic/HKD.hs @@ -67,41 +67,29 @@ field field = G.field' @field --- | When we work with records, all the fields are named, and we can refer to --- them using these names. This class provides a lens from our HKD structure to --- any @f@-wrapped field. +-- | Product types /without/ named fields can't be addressed by field name (for +-- very obvious reason), so we instead need to address them with their +-- "position" index. This is a one-indexed type-applied natural: -- --- >>> :set -XDataKinds -XDeriveGeneric --- >>> import Control.Lens ((&), (.~)) --- >>> import Data.Monoid (Last) --- >>> import GHC.Generics +-- >>> import Control.Lens ((^.)) -- --- >>> data User = User { name :: String, age :: Int } deriving (Generic, Show) --- >>> type Partial a = HKD a Last +-- >>> :t mempty @(HKD (Int, String) []) ^. position @1 +-- mempty @(HKD (Int, String) []) ^. position @1 :: [Int] -- --- We can create an empty partial @User@ and set its name to \"Tom\" (which, in --- this case, is @pure \"Tom\" :: Last String@): +-- As we're using the wonderful @generic-lens@ library under the hood, we also +-- get some beautiful error messages when things go awry: -- --- >>> mempty @(Partial User) & field @"name" .~ pure "Tom" --- User {name = Last {getLast = Just "Tom"}, age = Last {getLast = Nothing}} --- --- Thanks to some @generic-lens@ magic, we also get some pretty magical type --- errors! If we create a (complete) partial user: --- --- >>> import Data.Generic.HKD.Construction (deconstruct) --- >>> total = deconstruct @Last (User "Tom" 25) --- --- ... and then try to access a field that isn't there, we get a friendly --- message to point us in the right direction: --- --- >>> total & field @"oops" .~ pure () +-- >>> import Data.Generic.HKD.Construction +-- >>> deconstruct ("Hello", True) ^. position @4 -- ... -- ... error: --- ... • The type HKD User Last does not contain a field named 'oops'. +-- ... • The type HKD +-- ... ([Char], Bool) f does not contain a field at position 4 -- ... position :: forall index f structure inner . G.HasPosition' index (HKD structure f) (f inner) => G.Lens' (HKD structure f) (f inner) + position = G.position' @index