    {-# LANGUAGE CPP #-}
    {-# OPTIONS_HADDOCK hide #-}

    #include "containers.h"

    module Utils.Containers.Internal.Coercions where

    #ifdef __GLASGOW_HASKELL__
    import Data.Coerce
    #endif

    infixl 8 .#
    #ifdef __GLASGOW_HASKELL__
    (.#) :: Coercible b a => (b -> c) -> (a -> b) -> a -> c
    .# :: forall b a c. Coercible b a => (b -> c) -> (a -> b) -> a -> c
    (.#) b -> c
    f a -> b
    _ = (b -> c) -> a -> c
    forall a b. Coercible a b => a -> b
    coerce b -> c
    f
    #else
    (.#) :: (b -> c) -> (a -> b) -> a -> c
    (.#) = (.)
    #endif
    {-# INLINE (.#) #-}

    infix 9 .^#

    -- | Coerce the second argument of a function. Conceptually,
    -- can be thought of as:
    --
    -- @
    --   (f .^# g) x y = f x (g y)
    -- @
    --
    -- However it is most useful when coercing the arguments to
    -- 'foldl':
    --
    -- @
    --   foldl f b . fmap g = foldl (f .^# g) b
    -- @
    #ifdef __GLASGOW_HASKELL__
    (.^#) :: Coercible c b => (a -> c -> d) -> (b -> c) -> (a -> b -> d)
    .^# :: forall c b a d.
    Coercible c b =>
    (a -> c -> d) -> (b -> c) -> a -> b -> d
    (.^#) a -> c -> d
    f b -> c
    _ = (a -> c -> d) -> a -> b -> d
    forall a b. Coercible a b => a -> b
    coerce a -> c -> d
    f
    #else
    (.^#) :: (a -> c -> d) -> (b -> c) -> (a -> b -> d)
    (f .^# g) x y = f x (g y)
    #endif
    {-# INLINE (.^#) #-}