    {-# LANGUAGE TypeOperators #-}

    -- | First-class type families
    --
    -- For example, here is a regular type family:
    --
    -- @
    -- type family   FromMaybe (a :: k) (m :: Maybe k) :: k
    -- type instance FromMaybe a 'Nothing  = a
    -- type instance FromMaybe a ('Just b) = b
    -- @
    --
    -- With @Fcf@, it translates to a @data@ declaration:
    --
    -- @
    -- data FromMaybe :: k -> Maybe k -> 'Exp' k
    -- type instance 'Eval' (FromMaybe a 'Nothing)  = a
    -- type instance 'Eval' (FromMaybe a ('Just b)) = b
    -- @
    --
    -- - Fcfs can be higher-order.
    -- - The kind constructor 'Exp' is a monad: there's @('=<<')@ and 'Pure'.
    --
    -- Essential language extensions for "Fcf":
    --
    -- > {-# LANGUAGE
    -- >     DataKinds,
    -- >     PolyKinds,
    -- >     TypeFamilies,
    -- >     TypeInType,
    -- >     TypeOperators,
    -- >     UndecidableInstances #-}

    module Fcf
      ( -- * First-class type families

        Exp
      , Eval
      , type (@@)

        -- ** Functional combinators

      , Pure
      , Pure1
      , Pure2
      , Pure3
      , type (=<<)
      , type (<=<)
      , LiftM
      , LiftM2
      , LiftM3
      , Join
      , type (<$>)
      , type (<*>)
      , Flip
      , ConstFn
      , type ($)

        -- * Operations on common types

        -- ** Pairs

      , Uncurry
      , Fst
      , Snd
      , type (***)

        -- ** Either

      , UnEither
      , IsLeft
      , IsRight

        -- ** Maybe

      , UnMaybe
      , FromMaybe
      , IsNothing
      , IsJust

        -- ** Lists

      , Foldr
      , UnList
      , type (++)
      , Filter
      , Head
      , Tail
      , Null
      , Length
      , Find
      , FindIndex
      , Lookup
      , SetIndex
      , ZipWith
      , Zip
      , Unzip
      , Cons2

        -- ** Bool

      , UnBool
      , type (||)
      , type (&&)
      , Not

        -- ** Case splitting

      , Case
      , Match()
      , type (-->)
      , Is
      , Any
      , Else

        -- ** Nat

      , type (+)
      , type (-)
      , type (Fcf.Data.Nat.*)
      , type (^)
      , type (<=)
      , type (>=)
      , type (<)
      , type (>)

        -- * Overloaded operations

      , Map
      , Bimap

        -- * Miscellaneous

      , Error
      , Constraints
      , TyEq
      , Stuck
      , IsBool(_If)
      , If

      ) where

    import Fcf.Core
    import Fcf.Combinators
    import Fcf.Data.Bool
    import Fcf.Data.Common
    import Fcf.Data.List
    import Fcf.Data.Nat
    import Fcf.Class.Functor
    import Fcf.Class.Bifunctor
    import Fcf.Utils