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

-- $setup
-- >>> import Data.Void
-- >>> import Prelude

-- | '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 = Proxy deriving ( Bounded -- ^ @since 4.7.0.0
                              , Read    -- ^ @since 4.7.0.0
                              )

-- | 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 :: Type) = 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.

-- | @since 4.7.0.0
instance Eq (Proxy s) where
  _ == :: Proxy s -> Proxy s -> Bool
== _ = Bool
True

-- | @since 4.7.0.0
instance Ord (Proxy s) where
  compare :: Proxy s -> Proxy s -> Ordering
compare _ _ = Ordering
EQ

-- | @since 4.7.0.0
instance Show (Proxy s) where
  showsPrec :: Int -> Proxy s -> ShowS
showsPrec _ _ = String -> ShowS
showString "Proxy"

-- | @since 4.7.0.0
instance Enum (Proxy s) where
    succ :: Proxy s -> Proxy s
succ _               = String -> Proxy s
forall a. String -> a
errorWithoutStackTrace "Proxy.succ"
    pred :: Proxy s -> Proxy s
pred _               = String -> Proxy s
forall a. String -> a
errorWithoutStackTrace "Proxy.pred"
    fromEnum :: Proxy s -> Int
fromEnum _           = 0
    toEnum :: Int -> Proxy s
toEnum 0             = Proxy s
forall k (t :: k). Proxy t
Proxy
    toEnum _             = String -> Proxy s
forall a. String -> a
errorWithoutStackTrace "Proxy.toEnum: 0 expected"
    enumFrom :: Proxy s -> [Proxy s]
enumFrom _           = [Proxy s
forall k (t :: k). Proxy t
Proxy]
    enumFromThen :: Proxy s -> Proxy s -> [Proxy s]
enumFromThen _ _     = [Proxy s
forall k (t :: k). Proxy t
Proxy]
    enumFromThenTo :: Proxy s -> Proxy s -> Proxy s -> [Proxy s]
enumFromThenTo _ _ _ = [Proxy s
forall k (t :: k). Proxy t
Proxy]
    enumFromTo :: Proxy s -> Proxy s -> [Proxy s]
enumFromTo _ _       = [Proxy s
forall k (t :: k). Proxy t
Proxy]

-- | @since 4.7.0.0
instance Ix (Proxy s) where
    range :: (Proxy s, Proxy s) -> [Proxy s]
range _           = [Proxy s
forall k (t :: k). Proxy t
Proxy]
    index :: (Proxy s, Proxy s) -> Proxy s -> Int
index _ _         = 0
    inRange :: (Proxy s, Proxy s) -> Proxy s -> Bool
inRange _ _       = Bool
True
    rangeSize :: (Proxy s, Proxy s) -> Int
rangeSize _       = 1
    unsafeIndex :: (Proxy s, Proxy s) -> Proxy s -> Int
unsafeIndex _ _   = 0
    unsafeRangeSize :: (Proxy s, Proxy s) -> Int
unsafeRangeSize _ = 1

-- | @since 4.9.0.0
instance Semigroup (Proxy s) where
    _ <> :: Proxy s -> Proxy s -> Proxy s
<> _ = Proxy s
forall k (t :: k). Proxy t
Proxy
    sconcat :: NonEmpty (Proxy s) -> Proxy s
sconcat _ = Proxy s
forall k (t :: k). Proxy t
Proxy
    stimes :: b -> Proxy s -> Proxy s
stimes _ _ = Proxy s
forall k (t :: k). Proxy t
Proxy

-- | @since 4.7.0.0
instance Monoid (Proxy s) where
    mempty :: Proxy s
mempty = Proxy s
forall k (t :: k). Proxy t
Proxy
    mconcat :: [Proxy s] -> Proxy s
mconcat _ = Proxy s
forall k (t :: k). Proxy t
Proxy

-- | @since 4.7.0.0
instance Functor Proxy where
    fmap :: (a -> b) -> Proxy a -> Proxy b
fmap _ _ = Proxy b
forall k (t :: k). Proxy t
Proxy
    {-# INLINE fmap #-}

-- | @since 4.7.0.0
instance Applicative Proxy where
    pure :: a -> Proxy a
pure _ = Proxy a
forall k (t :: k). Proxy t
Proxy
    {-# INLINE pure #-}
    _ <*> :: Proxy (a -> b) -> Proxy a -> Proxy b
<*> _ = Proxy b
forall k (t :: k). Proxy t
Proxy
    {-# INLINE (<*>) #-}

-- | @since 4.9.0.0
instance Alternative Proxy where
    empty :: Proxy a
empty = Proxy a
forall k (t :: k). Proxy t
Proxy
    {-# INLINE empty #-}
    _ <|> :: Proxy a -> Proxy a -> Proxy a
<|> _ = Proxy a
forall k (t :: k). Proxy t
Proxy
    {-# INLINE (<|>) #-}

-- | @since 4.7.0.0
instance Monad Proxy where
    _ >>= :: Proxy a -> (a -> Proxy b) -> Proxy b
>>= _ = Proxy b
forall k (t :: k). Proxy t
Proxy
    {-# INLINE (>>=) #-}

-- | @since 4.9.0.0
instance MonadPlus Proxy

-- | '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.
--
-- >>> import Data.Word
-- >>> :type asProxyTypeOf 123 (Proxy :: Proxy Word8)
-- asProxyTypeOf 123 (Proxy :: Proxy Word8) :: Word8
--
-- Note the lower-case @proxy@ in the definition. This allows any type
-- constructor with just one argument to be passed to the function, for example
-- we could also write
--
-- >>> import Data.Word
-- >>> :type asProxyTypeOf 123 (Just (undefined :: Word8))
-- asProxyTypeOf 123 (Just (undefined :: Word8)) :: Word8
asProxyTypeOf :: a -> proxy a -> a
asProxyTypeOf :: a -> proxy a -> a
asProxyTypeOf = a -> proxy a -> a
forall a b. a -> b -> a
const
{-# INLINE asProxyTypeOf #-}