-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A library for generic programming that aims to be easy to understand
--
-- Documentation is here: https://generics-eot.readthedocs.io/
@package generics-eot
@version 0.4.0.1
-- | generics-eot tries to be a library for datatype generic
-- programming that is easy to understand. "eot" stands for "eithers of
-- tuples".
--
-- A tutorial on how to use generics-eot can be found here:
-- https://generics-eot.readthedocs.io/.
module Generics.Eot
-- | An instance (HasEot a) allows us to
--
--
-- - convert values of an arbitrary algebraic datatype a to
-- and from a generic representation (Eot a) (see
-- toEot and fromEot).
-- - extract meta information about the type a (see
-- datatype).
--
--
-- Once an algebraic datatype has an instance for Generic it
-- automatically gets one for HasEot.
class HasEot a where {
-- | Eot is a type level function that maps arbitrary ADTs to
-- isomorphic generic representations. Here's an example:
--
--
-- data Foo = A Int Bool | B String
--
--
-- would be mapped to:
--
--
-- Either (Int, (Bool, ())) (Either (String, ()) Void)
--
--
-- These representations follow these rules:
--
--
-- - The choice between constructors is mapped to right-nested
-- Eithers.
-- - There's always a so-called end-marker Void. It's an invalid
-- choice (and Void is uninhabited to make sure you don't
-- accidentally create such a value). So e.g. data Foo = A would
-- be mapped to Either () Void, and a type with no constructors
-- is mapped to Void.
-- - The fields of one constructor are mapped to right-nested
-- tuples.
-- - Again there's always an end-marker, this time of type ().
-- A constructor with three fields a, b, c is
-- mapped to (a, (b, (c, ()))), one field a is mapped
-- to (a, ()), and no fields are mapped to () (just the
-- end-marker).
--
--
-- These rules (and the end-markers) are necessary to make sure generic
-- functions know exactly which parts of the generic representation are
-- field types and which parts belong to the generic skeleton.
type family Eot a :: *;
}
-- | Convert a value of type a to its generic representation.
toEot :: HasEot a => a -> Eot a
-- | Convert a value in a generic representation to a (inverse of
-- toEot).
fromEot :: HasEot a => Eot a -> a
-- | Extract meta information about the ADT.
datatype :: HasEot a => Proxy a -> Datatype
-- | Type for meta information about ADTs.
data Datatype
Datatype :: String -> [Constructor] -> Datatype
-- | unqualified name of the type
[datatypeName] :: Datatype -> String
[constructors] :: Datatype -> [Constructor]
data Constructor
Constructor :: String -> Fields -> Constructor
[constructorName] :: Constructor -> String
[fields] :: Constructor -> Fields
-- | Type that represents meta information about fields of one constructor.
data Fields
-- | Record constructor, containing the list of the selector names.
Selectors :: [String] -> Fields
-- | Constructor with fields, but without selector names. The argument
-- gives the number of fields.
NoSelectors :: Int -> Fields
-- | Constructor without fields.
NoFields :: Fields
-- | Representable types of kind *. This class is derivable in GHC
-- with the DeriveGeneric flag on.
--
-- A Generic instance must satisfy the following laws:
--
--
-- from . to ≡ id
-- to . from ≡ id
--
class Generic a
-- | Proxy is a type that holds no data, but has a phantom parameter
-- of arbitrary type (or even kind). Its use is to provide type
-- information, even though there is no value available of that type (or
-- it may be too costly to create one).
--
-- Historically, Proxy :: Proxy a is a safer
-- alternative to the 'undefined :: a' idiom.
--
--
-- >>> Proxy :: Proxy (Void, Int -> Int)
-- Proxy
--
--
-- Proxy can even hold types of higher kinds,
--
--
-- >>> Proxy :: Proxy Either
-- Proxy
--
--
--
-- >>> Proxy :: Proxy Functor
-- Proxy
--
--
--
-- >>> Proxy :: Proxy complicatedStructure
-- Proxy
--
data Proxy (t :: k) :: forall k. () => k -> Type
Proxy :: Proxy
-- | Uninhabited data type
data Void
-- | Since Void values logically don't exist, this witnesses the
-- logical reasoning tool of "ex falso quodlibet".
--
--
-- >>> let x :: Either Void Int; x = Right 5
--
-- >>> :{
-- case x of
-- Right r -> r
-- Left l -> absurd l
-- :}
-- 5
--
absurd :: () => Void -> a
instance (GHC.Generics.Generic a, Generics.Eot.ImpliedByGeneric a c f) => Generics.Eot.HasEot a