Type families/data families

Type families/data families

https://stackoverflow.com/questions/20870432/type-family-vs-data-family-in-brief

import Data.ByteString as S
import Data.ByteString.Lazy as L

-- Declare a family of type synonyms, called `Element` 
-- `Element` has kind `* -> *`; it takes one parameter, which we call `container`
type family Element container

-- ByteString is a container for Word8, so...
-- The Element of a `S.ByteString` is a `Word8`
type instance Element S.ByteString = Word8 

-- and the Element of a `L.ByteString` is also `Word8`
type instance Element L.ByteString = Word8  

This is a type family - you pass different type params and get different types, ie, it's a family (of types) or a function on types. The left hand side of = and the right hand side of = - are equals in types sense and you can pass to a function expecting Word8 - a Element L.ByteString and vice versa - they are equal as types (something like a family of aliases).

Such family can be closed as well:

type family F a where
  F Int = Maybe Int
  F Bool = Int 

But also there are ''data family'':

-- Declare a list-like data family
data family XList a

-- Declare a list-like instance for Char
data instance XList Char = XCons Char (XList Char) | XNil

-- Declare a number-like instance for ()
data instance XList () = XListUnit Int

-- ERROR: "Multiple declarations of `XListUnit'"
data instance XList () = XListUnit Bool
-- (Note: GHCI accepts this; the new declaration just replaces the previous one.)

They are similar (types/data families) but on the right hand side - it's a new type, look, it has a constructor even! For example, XCons ... and you cannot use one type where another one was expected. Instances must not repeat by arguments (see the ERROR in the example).

Also:

<<< Usually, type synonyms are just abbreviations, but type family synonyms have added power: They can make a simple type (kind /) become a synonym of a "type with kind / -> * applied to an argument": <<<

type instance F A = B