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

Modulebarbies-2.1.1.0Haskell2010

Barbies.Bare

Sometimes one needs a type like Barbie Identity and it may feel like a second-class record type, where one needs to unpack values in each field. For those cases, we can leverage on closed type-families:

data Bare
data Covered

type family Wear t f a where
  Wear Bare    f a = a
  Wear Covered f a = f a

data SignUpForm t f
  = SignUpForm
      { username  :: Wear t f String,
      , password  :: Wear t f String
      , mailingOk :: Wear t f Bool
      }
 instance FunctorB (SignUpForm Covered)
 instance TraversableB (SignUpForm Covered)
 ...,
 instance BareB SignUpForm

type SignUpRaw  = SignUpForm Covered Maybe
type SignUpData = SignUpForm Bare Identity

formData = SignUpForm "jbond" "shaken007" False :: SignUpData
  • 2 types
  • 1 class
  • 2 values
  • Packagebarbies-2.1.1.0
  • Exports7
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceBare.hs

Bare values

3 declarations
familytype family Wear t (f :: Type -> Type) a where
#

The Wear type-function allows one to define a Barbie-type as

data B t f
  = B { f1 :: Wear t f Int
      , f2 :: Wear t f Bool
      }

This gives rise to two rather different types:

  • B Covered f is a normal Barbie-type, in the sense that f1 :: B Covered f -> f Int, etc.

  • B Bare f, on the other hand, is a normal record with no functor around the type:

B { f1 :: 5, f2 = True } :: B Bare f

Equations

datadata Bare
#
Instances3GBare
datadata Covered
#
Instances3GBare

Covering and stripping

4 declarations
familytype family WearTwo t (f :: Type -> Type) (g :: Type -> Type) a where
#

Like the Wear family, but with two wrappers f and g instead of one. This is useful if you have a data-type where f is parametric but g is not, consider this:

data T t f =
  T { f1 :: Wear    t f [Bool]
    , f2 :: Wear    t f (Sum Int)
    , f3 :: WearTwo t f Sum Int
    , f4 :: WearTwo t f Max Int
    }

with x :: T Covered Option we would have

f1 x :: IO (Option [Bool])
f2 x :: IO (Option (Sum Int))
f3 x :: IO (Option (Sum Int))
f4 x :: IO (Option (Max Int))

and with y :: T Bare Identity we would have

f1 y :: Int
f2 y :: Sum Int
f3 y :: Int
f4 y :: Int

Note how (Option (Sum Int)) (or Max) has a nice Semigroup instance that we can use to merge two (covered) barbies, while WearTwo removes the wrapper for the bare barbie.

Equations