HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulegeneric-optics-2.2.1.0Haskell2010

Data.Generics.Product.Types

Derive traversals of a given type in a product.

  • 1 type
  • 3 classes
  • 2 values

Traversals

2 declarations

Running example:

Example6 expressions
:set -XTypeApplications:set -XDeriveGeneric:set -XScopedTypeVariablesimport GHC.Genericsimport Optics.Core:{data WTree a w  = Leaf a  | Fork (WTree a w) (WTree a w)  | WithWeight (WTree a w) w  deriving (Generic, Show):}
classclass HasTypes s a where
#
Instances3HasTypes
  • HasTypes Void aDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
  • HasTypes s VoidDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
  • HasTypesUsing ChGeneric s s a a => HasTypes s aDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
valuetypes :: HasTypes s a => Traversal' s a
#

Traverse all types in the given structure.

For example, to update all Strings in a WTree (Maybe String) String, we can write

Example2 expressions
myTree = WithWeight (Fork (Leaf (Just "hello")) (Leaf Nothing)) "world"over (types @String) (++ "!") myTreeWithWeight (Fork (Leaf (Just "hello!")) (Leaf Nothing)) "world!"

The traversal is deep, which means that not just the immediate children are visited, but all nested values too.

Custom traversal strategies

5 declarations

The default traversal strategy types recurses into each node of the type using the Generic instance for the nodes. However, in general not all nodes will have a Generic instance. For example:

Example3 expressions
data Opaque = Opaque String deriving ShowmyTree = WithWeight (Fork (Leaf (Opaque "foo")) (Leaf (Opaque "bar"))) Falseover (types @String) (++ "!") myTree...... | No instance for ‘Generic Opaque’... |   arising from a generic traversal.... |   Either derive the instance, or define a custom traversal using HasTypesCustom...

In these cases, we can define a custom traversal strategy to override the generic behaviour for certain types. For a self-contained example, see the CustomChildren module in the tests directory.

familytype family Children ch a :: [Type]
#

The children of a type are the types of its fields. The Children type family maps a type a to its set of children.

This type family is parameterized by a symbol ch (that can be declared as an empty data type). The symbol ChGeneric provides a default definition. You can create new symbols to override the set of children of abstract, non-generic types.

The following example declares a Custom symbol to redefine Children for some abstract types from the time library.

data Custom
type instance Children Custom a = ChildrenCustom a

type family ChildrenCustom (a :: Type) where
  ChildrenCustom DiffTime        = '[]
  ChildrenCustom NominalDiffTime = '[]
  -- Add more custom mappings here.

  ChildrenCustom a = Children ChGeneric a

To use this definition, replace types with typesUsing @Custom.

Instances1Children
datadata ChGeneric
#

The default definition of Children. Primitive types from core libraries have no children, and other types are assumed to be Generic.

Instances2GHasTypes, Children
  • HasTypes b a => GHasTypes ChGeneric (Rec0 b) (Rec0 b) a aDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types

    The default instance for HasTypes acts as a synonym for 'HasTypesUsing ChGeneric', so in most cases this instance should behave the same as the one above. However, there might be overlapping instances defined for HasTypes directly, in which case we want to prefer those instances (even though the custom instances should always be added to HasTypesCustom)

  • type Children ChGeneric a = ChildrenDefault aDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
classclass HasTypesUsing ch s t a b where
#
Instances4HasTypesUsing
  • HasTypesOpt ch (Interesting ch a s) s t a b => HasTypesUsing ch s t a bDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
  • HasTypesUsing ch Void Void a bDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
  • HasTypesUsing ch a b a bDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
  • HasTypesUsing ch s s Void VoidDefined in generic-lens-core-2.2.1.0 · Data.Generics.Product.Internal.Types
classclass HasTypesCustom ch s t a b where
#

By adding instances to this class, we can override the default behaviour in an ad-hoc manner. For example:

instance HasTypesCustom Custom Opaque Opaque String String where
  typesCustom f (Opaque str) = Opaque $ f str

Methods

  • typesCustom :: Traversal s t a b

    This function should never be used directly, only to override the default traversal behaviour. To actually use the custom traversal strategy, see typesUsing. This is because typesUsing does additional optimisations, like ensuring that nodes with no relevant members will not be traversed at runtime.

Instances1HasTypesCustom