# How do type families with no equations work?

**URL:** <https://discourse.haskell.org/t/how-do-type-families-with-no-equations-work/13377>\
**Category:** Learn\
**Created:** [December 8, 2025, 3:34pm UTC](https://discourse.haskell.org/t/how-do-type-families-with-no-equations-work/13377 "2025-12-08T15:34:40Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![ashokkimmel](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ashokkimmel/32/5111_2.png) [@ashokkimmel](https://discourse.haskell.org/u/ashokkimmel)\
**Post date:** [December 8, 2025, 3:34pm UTC](https://discourse.haskell.org/t/how-do-type-families-with-no-equations-work/13377/1 "2025-12-08T15:34:41Z")

</div>

The package constraints shows these type families:  
[type family Take :: Nat → Symbol → Symbol where  
type family Drop :: Nat → Symbol → Symbol where  
type family Length :: Symbol → Nat where](https://hackage.haskell.org/package/constraints-0.14.2/src/src/Data/Constraint/Symbol.hs)

This is similar to GHC.TypeLits, which features

```haskell
type family AppendSymbol (m ::Symbol) (n :: Symbol) :: Symbol
type family ConsSymbol (a :: Char) (b :: Symbol) :: Symbol

```

I used to think these were magically defined through GHC/Base internal magic, but they also occur in `Data.Constraint.Symbol`. Could I define them myself?

---

<div class="post-metadata">

**Author:** ![raehik](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/raehik/32/5337_2.png) [@raehik](https://discourse.haskell.org/u/raehik)\
**Post date:** [December 8, 2025, 4:32pm UTC](https://discourse.haskell.org/t/how-do-type-families-with-no-equations-work/13377/2 "2025-12-08T16:32:51Z")

</div>

I think these _are_ empty type families, meaning they don’t reduce. I can confirm that behaviour opening the package in a repl: `:k! Take 1 "hi"` spits out `Take 1 "hi"`. I think the package’s focus wasn’t on type-level computation. (Also, back in the day, you couldn’t deconstruct `Symbol`s.)

You can define `AppendSymbol` and `ConsSymbol` yourself if you want, but those type families are indeed “magical” in GHC, and will perform faster than anything you write. (I know they look similarly empty in the Hackage source ([GHC.Internal.TypeLits](https://hackage.haskell.org/package/ghc-internal-9.1201.0/docs/src/GHC.Internal.TypeLits.html#AppendSymbol)), but they are handled specially in the compiler-- see `compiler/GHC/Builtin/Types/Literals.hs`.)
