HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulebarbies-2.1.1.0Haskell2010

Data.Functor.Barbie

Functors from indexed-types to types.

  • 2 types
  • 5 classes
  • 25 values
  • Packagebarbies-2.1.1.0
  • Exports32
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceBarbie.hs

Functor

1 declaration
classclass FunctorB (b :: (k -> Type) -> Type) where
#

Barbie-types that can be mapped over. Instances of FunctorB should satisfy the following laws:

bmap id = id
bmap f . bmap g = bmap (f . g)

There is a default bmap implementation for Generic types, so instances can derived automatically.

Methods

  • bmap :: (forall (a :: k). f a -> g a) -> b f -> b g
Instances10FunctorB, …

Traversable

1 declaration
classclass FunctorB b => TraversableB (b :: (k -> Type) -> Type) where
#

Barbie-types that can be traversed from left to right. Instances should satisfy the following laws:

 t . btraverse f   = btraverse (t . f)  -- naturality
btraverse Data.Functor.Identity = Data.Functor.Identity           -- identity
btraverse (Compose . fmap g . f) = Compose . fmap (btraverse g) . btraverse f -- composition

There is a default btraverse implementation for Generic types, so instances can derived automatically.

Methods

Instances10TraversableB, …

Utility functions

valuebfor
  1. :: (TraversableB b, Applicative e)
  2. => b f
  3. -> forall (a :: k). f a -> e (g a)
  4. -> e (b g)
#

btraverse with the arguments flipped. Useful when the traversing function is a large lambda:

bfor someBarbie $ fa -> ...
valuebtraverse_
  1. :: (TraversableB b, Applicative e)
  2. => forall (a :: k). f a -> e c
  3. -> b f
  4. -> e ()
#

Map each element to an action, evaluate these actions from left to right, and ignore the results.

valuebfoldMap
  1. :: (TraversableB b, Monoid m)
  2. => forall (a :: k). f a -> m
  3. -> b f
  4. -> m
#

Map each element to a monoid, and combine the results.

Distributive

5 declarations
classclass FunctorB b => DistributiveB (b :: (k -> Type) -> Type) where
#

A FunctorB where the effects can be distributed to the fields: bdistribute turns an effectful way of building a Barbie-type into a pure Barbie-type with effectful ways of computing the values of its fields.

This class is the categorical dual of TraversableB, with bdistribute the dual of bsequence and bcotraverse the dual of btraverse. As such, instances need to satisfy these laws:

bdistribute . h = bmap (Compose . h . getCompose) . bdistribute    -- naturality
bdistribute . Identity = bmap (Compose . Identity)                 -- identity
bdistribute . Compose = bmap (Compose . Compose . fmap getCompose . getCompose) . bdistribute . fmap bdistribute -- composition

By specializing f to ((->) a) and g to Identity, we can define a function that decomposes a function on distributive barbies into a collection of simpler functions:

bdecompose :: DistributiveB b => (a -> b Identity) -> b ((->) a)
bdecompose = bmap (fmap runIdentity . getCompose) . bdistribute

Lawful instances of the class can then be characterized as those that satisfy:

brecompose . bdecompose = id
bdecompose . brecompose = id

This means intuitively that instances need to have a fixed shape (i.e. no sum-types can be involved). Typically, this means record types, as long as they don't contain fields where the functor argument is not applied.

There is a default implementation of bdistribute based on Generic. Intuitively, it works on product types where the shape of a pure value is uniquely defined and every field is covered by the argument f.

Methods

Instances5DistributiveB
valuebdecompose :: DistributiveB b => (a -> b Identity) -> b ((->) a)
#

Decompose a function returning a distributive barbie, into a collection of simpler functions.

Applicative

1 declaration
classclass FunctorB b => ApplicativeB (b :: (k -> Type) -> Type) where
#

A FunctorB with application, providing operations to:

  • embed an "empty" value (bpure)

  • align and combine values (bprod)

It should satisfy the following laws:

Naturality of bprod
bmap ((Pair a b) -> Pair (f a) (g b)) (u `bprod' v) = bmap f u `bprod' bmap g v
Left and right identity
bmap ((Pair _ b) -> b) (bpure e `bprod' v) = v
bmap ((Pair a _) -> a) (u `bprod' bpure e) = u
Associativity
bmap ((Pair a (Pair b c)) -> Pair (Pair a b) c) (u `bprod' (v `bprod' w)) = (u `bprod' v) `bprod' w

It is to FunctorB in the same way as Applicative relates to Functor. For a presentation of Applicative as a monoidal functor, see Section 7 of Applicative Programming with Effects.

There is a default implementation of bprod and bpure based on Generic. Intuitively, it works on types where the value of bpure is uniquely defined. This corresponds rougly to record types (in the presence of sums, there would be several candidates for bpure), where every field is either a Monoid or covered by the argument f.

Methods

Instances7ApplicativeB, …

Utility functions

Constraints and instance dictionaries

2 declarations

Consider the following function:

showIt :: Show a => Maybe a -> Data.Functor.Const String a
showIt = Data.Functor.Const . show

We would then like to be able to do:

bmap showIt :: FunctorB b => b Maybe -> b (Data.Functor.Const String)

This however doesn't work because of the (Show a) constraint in the the type of showIt.

The ConstraintsB class let us overcome this problem.

classclass FunctorB b => ConstraintsB (b :: (k -> Type) -> Type) where
#

Instances of this class provide means to talk about constraints, both at compile-time, using AllB, and at run-time, in the form of Dict, via baddDicts.

A manual definition would look like this:

data T f = A (f Int) (f String) | B (f Bool) (f Int)

instance ConstraintsB T where
  type AllB c T = (c Int, c String, c Bool)

  baddDicts t = case t of
    A x y -> A (Pair Dict x) (Pair Dict y)
    B z w -> B (Pair Dict z) (Pair Dict w)

Now, when we given a T f, if we need to use the Show instance of their fields, we can use:

baddDicts :: AllB Show b => b f -> b (Dict Show `Product' f)

There is a default implementation of ConstraintsB for Generic types, so in practice one will simply do:

derive instance Generic (T f)
instance ConstraintsB T

Associated types

Methods

Instances8ConstraintsB, …

Utility functions

valuebmapC
  1. :: (AllB c b, ConstraintsB b)
  2. => forall (a :: k). c a => f a -> g a
  3. -> b f
  4. -> b g
#

Like bmap but a constraint is allowed to be required on each element of b

E.g. If all fields of b are Showable then you could store each shown value in it's slot using Const:

showFields :: (AllB Show b, ConstraintsB b) => b Identity -> b (Const String)
showFields = bmapC @Show showField
  where
    showField :: forall a. Show a => Identity a -> Const String a
    showField (Identity a) = Const (show a)

Notice that one can use the (&) class as a way to require several constraiints to hold simultaneously:

bmap @(Show & Eq & Enum) r

Support for generic derivations

1 declaration
newtypenewtype Rec p a (x :: k)
#

Constructors

Instances45GTraversable, GApplicative, GFunctor, GDistributive, GBare, GConstraints, …