    {-# LANGUAGE ConstraintKinds #-}
    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE ImpredicativeTypes #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE PolyKinds #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE AllowAmbiguousTypes #-}  -- See Note [withDict has an ambiguous type]
    {-# LANGUAGE Unsafe #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Magic.Dict
    -- Copyright   :  (c) The University of Glasgow 2009
    -- License     :  see libraries/ghc-prim/LICENSE
    --
    -- Maintainer  :  ghc-devs@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC Extensions)
    --
    -- Defines the 'withDict' function. For more information, see
    -- @Note [withDict]@ in "GHC.Tc.Instance.Class" in GHC.
    -- The definition of 'withDict' is located in a separate module from
    -- "GHC.Magic" because 'withDict' is @Unsafe@ (it threatens type class
    -- coherence) while "GHC.Magic" is @Trustworthy@.
    --
    -- Use "GHC.Exts" from the @base@ package instead of importing this
    -- module directly.
    --
    -----------------------------------------------------------------------------

    module GHC.Magic.Dict (
        WithDict( withDict )
      ) where

    import GHC.Types (RuntimeRep, TYPE)

    -- | The constraint @'WithDict' cls meth@ can be solved when evidence for
    -- the constraint @cls@ can be provided in the form of a dictionary of
    -- type @meth@. This requires @cls@ to be a class constraint whose single
    -- method has type @meth@.
    --
    -- For more (important) details on how this works, see
    -- @Note [withDict]@ in "GHC.Tc.Instance.Class" in GHC.
    --
    --   @since 0.9.0
    class WithDict cls meth where
      -- @'withDict' d f@ provides a way to call a type-class–overloaded function
      -- @f@ by applying it to the supplied dictionary @d@.
      --
      -- 'withDict' can only be used if the type class has a single method with no
      -- superclasses.
      --
      --   @since 0.9.0
      withDict :: forall {rr :: RuntimeRep} (r :: TYPE rr). meth -> (cls => r) -> r

    {- Note [withDict has an ambiguous type]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The type of `withDict` is ambiguous.  Consider
       foo :: forall cls meth. WithDict cls meth
           => forall rr (r::rr). meth -> (cls => r) -> r
       foo m k = withDict m k

    If we instantiate `withDict` with fresh unification variables, including cls0 for cls,
    there is nothing that forces the `cls` Wanted from the call to `k` to unify with the
    `cls0` Given from the call to `withDict`.  You have to give it a class argument:

       foo m k = withDict @cls m k

    That's fine.  But it means we need -XAllowAmbiguousTypes for the withDict definition,
    at least with deep subsumption.
    -}