Copyright | (c) Tom Harding 2019 |
---|---|
License | MIT |
Maintainer | tom.harding@habito.com |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
Documentation
class HasField' (field :: Symbol) (f :: Type -> Type) (structure :: Type) (focus :: Type) | field f structure -> focus where Source #
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.
>>>
:set -XDataKinds -XDeriveGeneric
>>>
import Control.Lens ((&), (.~))
>>>
import Data.Monoid (Last)
>>>
import GHC.Generics
>>>
data User = User { name :: String, age :: Int } deriving (Generic, Show)
>>>
type Partial a = HKD a Last
We can create an empty partial User
and set its name to "Tom" (which, in
this case, is pure "Tom" :: Last String
):
>>>
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 ()
... ... error: ... • The type User does not contain a field named 'oops'. ...