    {-# 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,

    -- >     TypeOperators,

    -- >     UndecidableInstances #-}

    module Fcf
      ( -- * First-class type families

        Exp
      , Eval
      , type (@@)

        -- ** Functional combinators

      , Pure
      , Pure1
      , Pure2
      , Pure3
      , Pure4
      , Pure5
      , Pure6
      , Pure7
      , Pure8
      , Pure9
      , type (=<<)
      , 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

      , type (++)
      , Head
      , Last
      , Tail
      , Cons
      , Snoc
      , Cons2
      , Init
      , Uncons
      , Unsnoc
      , Singleton
      , Null
      , Length
      , Reverse
      , Intersperse
      , Intercalate
      , Foldr
      , UnList
      , Concat
      , ConcatMap
      , Unfoldr
      , Replicate
      , Take
      , Drop
      , SplitAt
      , TakeWhile
      , DropWhile
      , Span
      , Break
      , Tails
      , IsPrefixOf
      , IsSuffixOf
      , IsInfixOf
      , Elem
      , Lookup
      , Find
      , Filter
      , Partition
      , FindIndex
      , SetIndex
      , ZipWith
      , Zip
      , Unzip

        -- ** 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
      , Assert
      , AssertNot

      ) 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