content: {-# LANGUAGE Trustworthy #-}
  {-# LANGUAGE NoImplicitPrelude #-}
  {-# LANGUAGE PolyKinds #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  Data.Proxy
  -- License     :  BSD-style (see the LICENSE file in the distribution)
  --
  -- Maintainer  :  libraries@haskell.org
  -- Stability   :  experimental
  -- Portability :  portable
  --
  -- Definition of a Proxy type (poly-kinded in GHC)
  --
  -- @since 4.7.0.0
  -----------------------------------------------------------------------------
  
  module Data.Proxy
    (
          Proxy(..), asProxyTypeOf
        , KProxy(..)
    ) where
  
  import GHC.Base
  import GHC.Show
  import GHC.Read
  import GHC.Enum
  import GHC.Arr
  
  -- | A concrete, poly-kinded proxy type
  data Proxy t = Proxy
  
  -- | A concrete, promotable proxy type, for use at the kind level
  -- There are no instances for this because it is intended at the kind level only
  data KProxy (t :: *) = KProxy
  
  -- It's common to use (undefined :: Proxy t) and (Proxy :: Proxy t)
  -- interchangeably, so all of these instances are hand-written to be
  -- lazy in Proxy arguments.
  
  instance Eq (Proxy s) where
    _ == _ = True
  
  instance Ord (Proxy s) where
    compare _ _ = EQ
  
  instance Show (Proxy s) where
    showsPrec _ _ = showString "Proxy"
  
  instance Read (Proxy s) where
    readsPrec d = readParen (d > 10) (\r -> [(Proxy, s) | ("Proxy",s) <- lex r ])
  
  instance Enum (Proxy s) where
      succ _               = error "Proxy.succ"
      pred _               = error "Proxy.pred"
      fromEnum _           = 0
      toEnum 0             = Proxy
      toEnum _             = error "Proxy.toEnum: 0 expected"
      enumFrom _           = [Proxy]
      enumFromThen _ _     = [Proxy]
      enumFromThenTo _ _ _ = [Proxy]
      enumFromTo _ _       = [Proxy]
  
  instance Ix (Proxy s) where
      range _           = [Proxy]
      index _ _         = 0
      inRange _ _       = True
      rangeSize _       = 1
      unsafeIndex _ _   = 0
      unsafeRangeSize _ = 1
  
  instance Bounded (Proxy s) where
      minBound = Proxy
      maxBound = Proxy
  
  instance Monoid (Proxy s) where
      mempty = Proxy
      mappend _ _ = Proxy
      mconcat _ = Proxy
  
  instance Functor Proxy where
      fmap _ _ = Proxy
      {-# INLINE fmap #-}
  
  instance Applicative Proxy where
      pure _ = Proxy
      {-# INLINE pure #-}
      _ <*> _ = Proxy
      {-# INLINE (<*>) #-}
  
  instance Monad Proxy where
      return _ = Proxy
      {-# INLINE return #-}
      _ >>= _ = Proxy
      {-# INLINE (>>=) #-}
  
  -- | 'asProxyTypeOf' is a type-restricted version of 'const'.
  -- It is usually used as an infix operator, and its typing forces its first
  -- argument (which is usually overloaded) to have the same type as the tag
  -- of the second.
  asProxyTypeOf :: a -> Proxy a -> a
  asProxyTypeOf = const
  {-# INLINE asProxyTypeOf #-}
  