# First-class instances GHC compiles type classes as data types. *first-class-instaces* makes that correspondence explicit with a simple but powerful mechanism to define instances. This enables implementations of [*deriving* as libraries](https://hackage.haskell.org/package/ad-lib). ## Overview ### Type classes as data types Type classes are associated to data types using the `mkDict` command. Example: ```haskell class Monoid a where mempty :: a (<>) :: a -> a -> a mkDict ''Monoid ``` That generates the following data type: ```haskell data DictMonoid a = Monoid { _mempty :: a , (|<>) :: a -> a -> a } ``` ### Dictionaries The `Dict` type family maps constraints to their corresponding dictionary types. ```haskell type family Dict (c :: Constraint) :: Type -- Defined in FCI type instance Dict (Monoid a) = DictMonoid a -- also from mkDict ''Monoid ``` A constraint `c` can be reflected as a dictionary: ```haskell dict @c :: c => Dict c ``` ### Instances from dictionaries A dictionary `d` can be reified as an instance. Example: ```haskell instanceDict [| d :: Dict (Monoid T) |] ``` That generates the following instance: ```haskell instance Monoid T where mempty = _mempty d (<>) = (|<>) d ``` ## Show me the types The core API of *first-class-instances*: ```haskell {- module FCI -} type Dict :: Constraint -> Type dict :: forall c. c => Dict c mkDict :: Name -> Q [Dec] instanceDict :: Q Type -> Q [Dec] {- module FCI.Unsafe -} (==>) :: forall c r. Dict c -> (c => r) -> r ``` ## Deriving as a library These simple primitives can be used to implement "deriving as a library". The adventure continues in [*ad-lib*](https://hackage.haskell.org/package/ad-lib). ## Related work - The [*reflection*](https://hackage.haskell.org/package/reflection) library is another approach to convert constraints into first-class values, and back. It provides a solution for implicit configuration, rather than deriving type class instances for user-defined types. - In Agda, [all data types are type classes](https://agda.readthedocs.io/en/latest/language/instance-arguments.html), exemplifying the orthogonality of declaring a data type, and passing values implicitly as instances. Haskell requires instances to be globally unique: there must not be two instances `Monoid T` for the same `T`.