Safe Haskell  None 

Language  Haskell2010 
A common Haskell idiom is to parameterise a datatype by a functor or GADT
(or any "indexed type" k >
), a pattern
sometimes called HKD).
This parameter acts like the outfit of a Barbie, turning it into a different
doll. The canonical example would be:Type
data Person f = Person { name :: fString
, age :: fInt
}
Let's say that we are writing an application where Person
data
will be read from a web form, validated, and stored in a database. Some
possibles outfits that we could use along the way are:
Person (Const
String
)  for the raw input from the webform, Person (Either
String
)  for the result of parsing and validating, PersonIdentity
 for the actual data, Person DbColumn  To describe how to read / write aPerson
to the db data DbColumn a = DbColumn { colName ::String
, fromDb :: DbDataParser a , toDb :: a > DbData }
In such application it is likely that one will have lots of types like
Person
so we will like to handle these transformations uniformly,
without boilerplate or repetitions. This package provides classes to
manipulate these types, using notions that are familiar to haskellers like
Functor
, Applicative
or Traversable
. For example, instead of writing
an adhoc function that checks that all fields have a correct value, like
checkPerson :: Person (Either
String
) >Either
[String
] (PersonIdentity
)
we can write only one such function:
check ::TraversableB
b => b (Either
String
) >Either
[String
] (bIdentity
) check be = casebtraverse
(either
(const
Nothing
) (Just
.Identity
)) be ofJust
bi >Right
biNothing
>Left
(bfoldMap
(either
(:[]) (const
[])) be)
Moreover, these classes come with default instances based on
Generic
, so using them is as easy as:
data Person f = Person { name :: fString
, age :: fInt
} deriving (Generic
,FunctorB
,TraversableB
,ApplicativeB
,ConstraintsB
) deriving instanceAllBF
Show
f Person =>Show
(Person f) deriving instanceAllBF
Eq
f Person =>Eq
(Person f)
Synopsis
 module Data.Functor.Barbie
 module Data.Functor.Transformer
 module Barbies.Bi
 newtype Container b a = Container {
 getContainer :: b (Const a)
 newtype ErrorContainer b e = ErrorContainer {
 getErrorContainer :: b (Either e)
 newtype Barbie (b :: (k > Type) > Type) f = Barbie {
 getBarbie :: b f
 data Void (f :: k > Type)
 data Unit (f :: k > Type) = Unit
Barbies are functors
Barbietypes are functors. That means that if one is familiar
with standard classes like Functor
, Applicative
or Traversable
,
one already knows how to work with barbietypes too. For instance, just
like one would use:
fmap
f (as :: [a])
to apply f
uniformly on every a
occurring
in as
, one could use the following to turn a Either
outfit
into Maybe
outfit:
bmap
(either
(const
Nothing
)Just
) (p :: Person (Either
e))
In this case, the argument of bmap
will have to be applied on all
fields of p
:
name p ::Either
eString
age p ::Either
eInt
So bmap
here demands a polymorphic function of type:
forall a .Either
e a >Maybe
a
That is why bmap
has a rank2 type:
bmap
::FunctorB
b => (forall a. f a > g a) > b f > b g
Polymorphic functions with Applicative
effects can be applied
using btraverse
and the effects will be accumulated:
btraverse
:: (TraversableB
b,Applicative
t) => (forall a. f a > t (g a)) > b f > t (b g)
Finally, some barbietypes (typically records like Person
) have an
Applicative
structure, and allow us to lift pure nary functions
to functions on barbietypes. For example, bzipWith
gives us an analogous
of liftA2
:
bzipWith
::ApplicativeB
b => (forall a. f a > g a > h a) > b f > b g > b h
We can use this to combine barbies:
addDefaults :: PersonMaybe
> PersonIdentity
> PersonIdentity
addDefaults =bzipWith
(\m d >maybe
dpure
m)
Why is there not a MonadB
class as well? As everyone knows,
a monad is just a monoid in the category of endofunctors,
which in this case is a problem, since barbietypes are not endofunctors:
they map indexedtypes to types, unlike the Functor
class, that
captures endofunctors on Type
.
All these classes, and other convenient functions are found in:
module Data.Functor.Barbie
Transformers are functors
Haskellers may be more used to playing with another family of dolls: transformers. Consider for example the following functortransformers:
Compose
g f aReaderT
r f aMaybeT
f a
Like with barbies, we can think that different choices of f
will
give us a different doll. And if we start thinking about how
to change the outfit of a transformer, we notice that, just like
barbietypes, transformertypes are functors too.
tmap
::FunctorT
t => (forall a. f a > g a) > t f x > b g x
Where FunctorB
captures functors from indexedtypes to types,
FunctorT
captures those between indexedtypes. And again, we can
identitfy familiar classes of functors: ApplicativeT
and TraversableT
.
Now, transformers like the ones above, are actually endofunctors, e.g.
they map
to itself. So it makes
sense to classify those that are actually monads: the Type
> Type
MonadT
class
gives us a notion similar to that of MonadTrans
,
in that it lets us lift a value to its transformed version:
tlift
::MonadT
t => f a > t f a  E.g., using the instance for Compose:tlift
[1, 2, 3] =Compose
(Just
[1, 2, 3]) ::Compose
Maybe
[]Int
Unlike all other classes in this package, MonadT
instances need to be written
by hand.
For further details, see:
module Data.Functor.Transformer
Bifunctors and nesting
A barbietype that is parametric on an additional functor can be made an
instance of both FunctorB
and FunctorT
. For example:
data B f g = B (f Int) (g Bool) deriving (Generic) instance FunctorB (B f) instance FunctorT B
This gives us a a bifunctor on indexedtypes, as we can map
simultaneously over both arguments using btmap
:
btmap
:: (FunctorB
(b f),FunctorT
b) => (forall a . f a > f' a) > (forall a . g a > g' a) > b f g > b f' g'
When f ~ g
, we can use a specialized version of btmap
:
btmap1
:: (FunctorB
(b f),FunctorT
b) => (forall a . f a > f' a) > b f f > b f' f'
Functions like btmap1
can be useful to handle cases where we would like
a barbietype to occur under the functorargument. Let's consider an example
of this. Continuing the web form example above, one may want to find out
about a person's dependants and model it as follows:
newtype Dependants f = Dependants { getDependants :: f [Person f] }
This has the appeal of letting us distinguish two states:
Dependants { getDependants = Just [] }  the user declared 0 dependants Dependants { getDependants = Nothing }  the user didn't specify dependants yet
Unfortunately, it is not possible to write a FunctorB
instance for such
a type (before going on, try to write one yourself!). Intuitively, we would
need to have
, which we can't assume. However, such a type
can be rewritten as follows:Functor
f
newtype Dependants f' f = Dependants { getDependants :: f' [Person f] } deriving (Generic) instance Functor f' => FunctorB (Dependants f') instance FunctorT Dependants type Dependants f = Dependants f f
We can thus use btmap1
as a poor man's version of bmap
for Dependants
.
For more details, see:
module Barbies.Bi
Containerbarbies
Some clothes make barbies look like containers, and we can make those
types behave like normal Functor
s.
newtype Container b a Source #
Wrapper for barbies that act as containers of a
by wearing (
.Const
a)
Container  

Instances
newtype ErrorContainer b e Source #
Wrapper for barbies that act as containers of e
by wearing
.Either
e
ErrorContainer  

Instances
Wrappers
This can be use with deriving via to automate derivation of instances for Barbietypes.
newtype Barbie (b :: (k > Type) > Type) f Source #
A wrapper for Barbietypes, providing useful instances.
Instances
FunctorB b => FunctorB (Barbie b :: (k > Type) > Type) Source #  
TraversableB b => TraversableB (Barbie b :: (k > Type) > Type) Source #  
Defined in Barbies.Internal.Wrappers  
ApplicativeB b => ApplicativeB (Barbie b :: (k > Type) > Type) Source #  
ConstraintsB b => ConstraintsB (Barbie b :: (k > Type) > Type) Source #  
ProductB b => ProductB (Barbie b :: (k > Type) > Type) Source #  
ProductBC b => ProductBC (Barbie b :: (k > Type) > Type) Source #  
Defined in Data.Barbie.Internal.ProductC  
(ConstraintsB b, ApplicativeB b, AllBF Semigroup f b) => Semigroup (Barbie b f) Source #  
(ConstraintsB b, ApplicativeB b, AllBF Semigroup f b, AllBF Monoid f b) => Monoid (Barbie b f) Source #  
type AllB (c :: k > Constraint) (Barbie b :: (k > Type) > Type) Source #  
Defined in Barbies.Internal.Wrappers 
Trivial Barbies
data Void (f :: k > Type) Source #
Uninhabited barbie type.
Instances
FunctorB (Void :: (k > Type) > Type) Source #  
TraversableB (Void :: (k > Type) > Type) Source #  
Defined in Barbies.Internal.Trivial  
ConstraintsB (Void :: (k > Type) > Type) Source #  
Eq (Void f) Source #  
Ord (Void f) Source #  
Show (Void f) Source #  
Generic (Void f) Source #  
Semigroup (Void f) Source #  
type AllB (c :: k > Constraint) (Void :: (k > Type) > Type) Source #  
type Rep (Void f) Source #  
data Unit (f :: k > Type) Source #
A barbie type without structure.
Instances
FunctorB (Unit :: (k > Type) > Type) Source #  
TraversableB (Unit :: (k > Type) > Type) Source #  
Defined in Barbies.Internal.Trivial  
DistributiveB (Unit :: (k > Type) > Type) Source #  
Defined in Barbies.Internal.Trivial  
ApplicativeB (Unit :: (k > Type) > Type) Source #  
ConstraintsB (Unit :: (k > Type) > Type) Source #  
ProductB (Unit :: (k > Type) > Type) Source #  
ProductBC (Unit :: (k > Type) > Type) Source #  
Defined in Data.Barbie.Internal.ProductC  
Eq (Unit f) Source #  
(Typeable f, Typeable k) => Data (Unit f) Source #  
Defined in Barbies.Internal.Trivial gfoldl :: (forall d b. Data d => c (d > b) > d > c b) > (forall g. g > c g) > Unit f > c (Unit f) # gunfold :: (forall b r. Data b => c (b > r) > c r) > (forall r. r > c r) > Constr > c (Unit f) # toConstr :: Unit f > Constr # dataTypeOf :: Unit f > DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) > Maybe (c (Unit f)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) > Maybe (c (Unit f)) # gmapT :: (forall b. Data b => b > b) > Unit f > Unit f # gmapQl :: (r > r' > r) > r > (forall d. Data d => d > r') > Unit f > r # gmapQr :: forall r r'. (r' > r > r) > r > (forall d. Data d => d > r') > Unit f > r # gmapQ :: (forall d. Data d => d > u) > Unit f > [u] # gmapQi :: Int > (forall d. Data d => d > u) > Unit f > u # gmapM :: Monad m => (forall d. Data d => d > m d) > Unit f > m (Unit f) # gmapMp :: MonadPlus m => (forall d. Data d => d > m d) > Unit f > m (Unit f) # gmapMo :: MonadPlus m => (forall d. Data d => d > m d) > Unit f > m (Unit f) #  
Ord (Unit f) Source #  
Read (Unit f) Source #  
Show (Unit f) Source #  
Generic (Unit f) Source #  
Semigroup (Unit f) Source #  
Monoid (Unit f) Source #  
type AllB (c :: k > Constraint) (Unit :: (k > Type) > Type) Source #  
type Rep (Unit f) Source #  