    {-# LANGUAGE DerivingVia #-}
    {-# LANGUAGE EmptyCase #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE InstanceSigs #-}
    {-# LANGUAGE StandaloneDeriving #-}
    {-# LANGUAGE Trustworthy #-}
    {-# LANGUAGE TypeOperators #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Functor.Contravariant
    -- Copyright   :  (C) 2007-2015 Edward Kmett
    -- License     :  BSD-style (see the file LICENSE)
    --
    -- Maintainer  :  libraries@haskell.org
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- 'Contravariant' functors, sometimes referred to colloquially as @Cofunctor@,
    -- even though the dual of a 'Functor' is just a 'Functor'. As with 'Functor'
    -- the definition of 'Contravariant' for a given ADT is unambiguous.
    --
    -- @since 4.12.0.0
    ----------------------------------------------------------------------------

    module Data.Functor.Contravariant (
      -- * Contravariant Functors
        Contravariant(..)
      , phantom

      -- * Operators
      , (>$<), (>$$<), ($<)

      -- * Predicates
      , Predicate(..)

      -- * Comparisons
      , Comparison(..)
      , defaultComparison

      -- * Equivalence Relations
      , Equivalence(..)
      , defaultEquivalence
      , comparisonEquivalence

      -- * Dual arrows
      , Op(..)
      ) where

    import Control.Applicative
    import GHC.Internal.Control.Category
    import GHC.Internal.Data.Function (on)

    import Data.Functor.Product
    import Data.Functor.Sum
    import Data.Functor.Compose

    import GHC.Internal.Data.Monoid (Alt(..), All(..))
    import GHC.Internal.Data.Proxy
    import GHC.Generics

    import Prelude hiding ((.), id)

    -- | The class of contravariant functors.
    --
    -- Whereas in Haskell, one can think of a 'Functor' as containing or producing
    -- values, a contravariant functor is a functor that can be thought of as
    -- /consuming/ values.
    --
    -- As an example, consider the type of predicate functions  @a -> Bool@. One
    -- such predicate might be @negative x = x < 0@, which
    -- classifies integers as to whether they are negative. However, given this
    -- predicate, we can re-use it in other situations, providing we have a way to
    -- map values /to/ integers. For instance, we can use the @negative@ predicate
    -- on a person's bank balance to work out if they are currently overdrawn:
    --
    -- @
    -- newtype Predicate a = Predicate { getPredicate :: a -> Bool }
    --
    -- instance Contravariant Predicate where
    --   contramap :: (a' -> a) -> (Predicate a -> Predicate a')
    --   contramap f (Predicate p) = Predicate (p . f)
    --                                          |   `- First, map the input...
    --                                          `----- then apply the predicate.
    --
    -- overdrawn :: Predicate Person
    -- overdrawn = contramap personBankBalance negative
    -- @
    --
    -- Any instance should be subject to the following laws:
    --
    -- [Identity]    @'contramap' 'id'      = 'id'@
    -- [Composition] @'contramap' (g . f) = 'contramap' f . 'contramap' g@
    --
    -- Note, that the second law follows from the free theorem of the type of
    -- 'contramap' and the first law, so you need only check that the former
    -- condition holds.

    class Contravariant f where
      contramap :: (a' -> a) -> (f a -> f a')

      -- | Replace all locations in the output with the same value.
      -- The default definition is @'contramap' . 'const'@, but this may be
      -- overridden with a more efficient version.
      (>$) :: b -> f b -> f a
      (>$) = (a -> b) -> f b -> f a
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap ((a -> b) -> f b -> f a) -> (b -> a -> b) -> b -> f b -> f a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a -> b
    forall a b. a -> b -> a
    const

    -- | If @f@ is both 'Functor' and 'Contravariant' then by the time you factor
    -- in the laws of each of those classes, it can't actually use its argument in
    -- any meaningful capacity.
    --
    -- This method is surprisingly useful. Where both instances exist and are
    -- lawful we have the following laws:
    --
    -- @
    -- 'fmap'      f ≡ 'phantom'
    -- 'contramap' f ≡ 'phantom'
    -- @
    phantom :: (Functor f, Contravariant f) => f a -> f b
    phantom :: forall (f :: * -> *) a b.
    (Functor f, Contravariant f) =>
    f a -> f b
    phantom f a
    x = () () -> f a -> f ()
    forall a b. a -> f b -> f a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ f a
    x f () -> () -> f b
    forall (f :: * -> *) b a. Contravariant f => f b -> b -> f a
    $< ()

    infixl 4 >$, $<, >$<, >$$<

    -- | This is '>$' with its arguments flipped.
    ($<) :: Contravariant f => f b -> b -> f a
    $< :: forall (f :: * -> *) b a. Contravariant f => f b -> b -> f a
    ($<) = (b -> f b -> f a) -> f b -> b -> f a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip b -> f b -> f a
    forall b a. b -> f b -> f a
    forall (f :: * -> *) b a. Contravariant f => b -> f b -> f a
    (>$)

    -- | This is an infix alias for 'contramap'.
    (>$<) :: Contravariant f => (a -> b) -> (f b -> f a)
    >$< :: forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
    (>$<) = (a -> b) -> f b -> f a
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap

    -- | This is an infix version of 'contramap' with the arguments flipped.
    (>$$<) :: Contravariant f => f b -> (a -> b) -> f a
    >$$< :: forall (f :: * -> *) b a. Contravariant f => f b -> (a -> b) -> f a
    (>$$<) = ((a -> b) -> f b -> f a) -> f b -> (a -> b) -> f a
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (a -> b) -> f b -> f a
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap

    deriving newtype instance Contravariant f => Contravariant (Alt f)
    deriving newtype instance Contravariant f => Contravariant (Rec1 f)
    deriving newtype instance Contravariant f => Contravariant (M1 i c f)

    instance Contravariant V1 where
      contramap :: (a' -> a) -> (V1 a -> V1 a')
      contramap :: forall a' a. (a' -> a) -> V1 a -> V1 a'
    contramap a' -> a
    _ V1 a
    x = case V1 a
    x of

    instance Contravariant U1 where
      contramap :: (a' -> a) -> (U1 a -> U1 a')
      contramap :: forall a' a. (a' -> a) -> U1 a -> U1 a'
    contramap a' -> a
    _ U1 a
    _ = U1 a'
    forall k (p :: k). U1 p
    U1

    instance Contravariant (K1 i c) where
      contramap :: (a' -> a) -> (K1 i c a -> K1 i c a')
      contramap :: forall a' a. (a' -> a) -> K1 i c a -> K1 i c a'
    contramap a' -> a
    _ (K1 c
    c) = c -> K1 i c a'
    forall k i c (p :: k). c -> K1 i c p
    K1 c
    c

    instance (Contravariant f, Contravariant g) => Contravariant (f :*: g) where
      contramap :: (a' -> a) -> ((f :*: g) a -> (f :*: g) a')
      contramap :: forall a' a. (a' -> a) -> (:*:) f g a -> (:*:) f g a'
    contramap a' -> a
    f (f a
    xs :*: g a
    ys) = (a' -> a) -> f a -> f a'
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f f a
    xs f a' -> g a' -> (:*:) f g a'
    forall k (f :: k -> *) (g :: k -> *) (p :: k).
    f p -> g p -> (:*:) f g p
    :*: (a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f g a
    ys

    instance (Functor f, Contravariant g) => Contravariant (f :.: g) where
      contramap :: (a' -> a) -> ((f :.: g) a -> (f :.: g) a')
      contramap :: forall a' a. (a' -> a) -> (:.:) f g a -> (:.:) f g a'
    contramap a' -> a
    f (Comp1 f (g a)
    fg) = f (g a') -> (:.:) f g a'
    forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (p :: k1).
    f (g p) -> (:.:) f g p
    Comp1 ((g a -> g a') -> f (g a) -> f (g a')
    forall a b. (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f) f (g a)
    fg)

    instance (Contravariant f, Contravariant g) => Contravariant (f :+: g) where
      contramap :: (a' -> a) -> ((f :+: g) a -> (f :+: g) a')
      contramap :: forall a' a. (a' -> a) -> (:+:) f g a -> (:+:) f g a'
    contramap a' -> a
    f (L1 f a
    xs) = f a' -> (:+:) f g a'
    forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
    L1 ((a' -> a) -> f a -> f a'
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f f a
    xs)
      contramap a' -> a
    f (R1 g a
    ys) = g a' -> (:+:) f g a'
    forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
    R1 ((a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f g a
    ys)

    instance (Contravariant f, Contravariant g) => Contravariant (Sum f g) where
      contramap :: (a' -> a) -> (Sum f g a -> Sum f g a')
      contramap :: forall a' a. (a' -> a) -> Sum f g a -> Sum f g a'
    contramap a' -> a
    f (InL f a
    xs) = f a' -> Sum f g a'
    forall {k} (f :: k -> *) (g :: k -> *) (a :: k). f a -> Sum f g a
    InL ((a' -> a) -> f a -> f a'
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f f a
    xs)
      contramap a' -> a
    f (InR g a
    ys) = g a' -> Sum f g a'
    forall {k} (f :: k -> *) (g :: k -> *) (a :: k). g a -> Sum f g a
    InR ((a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f g a
    ys)

    instance (Contravariant f, Contravariant g)
          => Contravariant (Product f g) where
      contramap :: (a' -> a) -> (Product f g a -> Product f g a')
      contramap :: forall a' a. (a' -> a) -> Product f g a -> Product f g a'
    contramap a' -> a
    f (Pair f a
    a g a
    b) = f a' -> g a' -> Product f g a'
    forall {k} (f :: k -> *) (g :: k -> *) (a :: k).
    f a -> g a -> Product f g a
    Pair ((a' -> a) -> f a -> f a'
    forall a' a. (a' -> a) -> f a -> f a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f f a
    a) ((a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f g a
    b)

    instance Contravariant (Const a) where
      contramap :: (b' -> b) -> (Const a b -> Const a b')
      contramap :: forall a' a. (a' -> a) -> Const a a -> Const a a'
    contramap b' -> b
    _ (Const a
    a) = a -> Const a b'
    forall {k} a (b :: k). a -> Const a b
    Const a
    a

    instance (Functor f, Contravariant g) => Contravariant (Compose f g) where
      contramap :: (a' -> a) -> (Compose f g a -> Compose f g a')
      contramap :: forall a' a. (a' -> a) -> Compose f g a -> Compose f g a'
    contramap a' -> a
    f (Compose f (g a)
    fga) = f (g a') -> Compose f g a'
    forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
    f (g a) -> Compose f g a
    Compose ((g a -> g a') -> f (g a) -> f (g a')
    forall a b. (a -> b) -> f a -> f b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a' -> a) -> g a -> g a'
    forall a' a. (a' -> a) -> g a -> g a'
    forall (f :: * -> *) a' a.
    Contravariant f =>
    (a' -> a) -> f a -> f a'
    contramap a' -> a
    f) f (g a)
    fga)

    instance Contravariant Proxy where
      contramap :: (a' -> a) -> (Proxy a -> Proxy a')
      contramap :: forall a' a. (a' -> a) -> Proxy a -> Proxy a'
    contramap a' -> a
    _ Proxy a
    _ = Proxy a'
    forall {k} (t :: k). Proxy t
    Proxy

    newtype Predicate a = Predicate { forall a. Predicate a -> a -> Bool
    getPredicate :: a -> Bool }
      deriving
        ( -- | @('<>')@ on predicates uses logical conjunction @('&&')@ on
          -- the results. Without newtypes this equals @'liftA2' (&&)@.
          --
          -- @
          -- (<>) :: Predicate a -> Predicate a -> Predicate a
          -- Predicate pred <> Predicate pred' = Predicate \a ->
          --   pred a && pred' a
          -- @
          NonEmpty (Predicate a) -> Predicate a
    Predicate a -> Predicate a -> Predicate a
    (Predicate a -> Predicate a -> Predicate a)
    -> (NonEmpty (Predicate a) -> Predicate a)
    -> (forall b. Integral b => b -> Predicate a -> Predicate a)
    -> Semigroup (Predicate a)
    forall b. Integral b => b -> Predicate a -> Predicate a
    forall a. NonEmpty (Predicate a) -> Predicate a
    forall a. Predicate a -> Predicate a -> Predicate a
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    forall a b. Integral b => b -> Predicate a -> Predicate a
    $c<> :: forall a. Predicate a -> Predicate a -> Predicate a
    <> :: Predicate a -> Predicate a -> Predicate a
    $csconcat :: forall a. NonEmpty (Predicate a) -> Predicate a
    sconcat :: NonEmpty (Predicate a) -> Predicate a
    $cstimes :: forall a b. Integral b => b -> Predicate a -> Predicate a
    stimes :: forall b. Integral b => b -> Predicate a -> Predicate a
    Semigroup
        , -- | @'mempty'@ on predicates always returns @True@. Without
          -- newtypes this equals @'pure' True@.
          --
          -- @
          -- mempty :: Predicate a
          -- mempty = \_ -> True
          -- @
          Semigroup (Predicate a)
    Predicate a
    Semigroup (Predicate a) =>
    Predicate a
    -> (Predicate a -> Predicate a -> Predicate a)
    -> ([Predicate a] -> Predicate a)
    -> Monoid (Predicate a)
    [Predicate a] -> Predicate a
    Predicate a -> Predicate a -> Predicate a
    forall a. Semigroup (Predicate a)
    forall a. Predicate a
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    forall a. [Predicate a] -> Predicate a
    forall a. Predicate a -> Predicate a -> Predicate a
    $cmempty :: forall a. Predicate a
    mempty :: Predicate a
    $cmappend :: forall a. Predicate a -> Predicate a -> Predicate a
    mappend :: Predicate a -> Predicate a -> Predicate a
    $cmconcat :: forall a. [Predicate a] -> Predicate a
    mconcat :: [Predicate a] -> Predicate a
    Monoid
        )
      via a -> All

      deriving
        ( -- | A 'Predicate' is a 'Contravariant' 'Functor', because
          -- 'contramap' can apply its function argument to the input of
          -- the predicate.
          --
          -- Without newtypes @'contramap' f@ equals precomposing with @f@
          -- (= @(. f)@).
          --
          -- @
          -- contramap :: (a' -> a) -> (Predicate a -> Predicate a')
          -- contramap f (Predicate g) = Predicate (g . f)
          -- @
          (forall a' a. (a' -> a) -> Predicate a -> Predicate a')
    -> (forall b a. b -> Predicate b -> Predicate a)
    -> Contravariant Predicate
    forall b a. b -> Predicate b -> Predicate a
    forall a' a. (a' -> a) -> Predicate a -> Predicate a'
    forall (f :: * -> *).
    (forall a' a. (a' -> a) -> f a -> f a')
    -> (forall b a. b -> f b -> f a) -> Contravariant f
    $ccontramap :: forall a' a. (a' -> a) -> Predicate a -> Predicate a'
    contramap :: forall a' a. (a' -> a) -> Predicate a -> Predicate a'
    $c>$ :: forall b a. b -> Predicate b -> Predicate a
    >$ :: forall b a. b -> Predicate b -> Predicate a
    Contravariant
        )
      via Op Bool

    -- | Defines a total ordering on a type as per 'compare'.
    --
    -- This condition is not checked by the types. You must ensure that the
    -- supplied values are valid total orderings yourself.
    newtype Comparison a = Comparison { forall a. Comparison a -> a -> a -> Ordering
    getComparison :: a -> a -> Ordering }
      deriving
      newtype
        ( -- | @('<>')@ on comparisons combines results with @('<>')
          -- \@Ordering@. Without newtypes this equals @'liftA2' ('liftA2'
          -- ('<>'))@.
          --
          -- @
          -- (<>) :: Comparison a -> Comparison a -> Comparison a
          -- Comparison cmp <> Comparison cmp' = Comparison \a a' ->
          --   cmp a a' <> cmp a a'
          -- @
          NonEmpty (Comparison a) -> Comparison a
    Comparison a -> Comparison a -> Comparison a
    (Comparison a -> Comparison a -> Comparison a)
    -> (NonEmpty (Comparison a) -> Comparison a)
    -> (forall b. Integral b => b -> Comparison a -> Comparison a)
    -> Semigroup (Comparison a)
    forall b. Integral b => b -> Comparison a -> Comparison a
    forall a. NonEmpty (Comparison a) -> Comparison a
    forall a. Comparison a -> Comparison a -> Comparison a
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    forall a b. Integral b => b -> Comparison a -> Comparison a
    $c<> :: forall a. Comparison a -> Comparison a -> Comparison a
    <> :: Comparison a -> Comparison a -> Comparison a
    $csconcat :: forall a. NonEmpty (Comparison a) -> Comparison a
    sconcat :: NonEmpty (Comparison a) -> Comparison a
    $cstimes :: forall a b. Integral b => b -> Comparison a -> Comparison a
    stimes :: forall b. Integral b => b -> Comparison a -> Comparison a
    Semigroup
        , -- | @'mempty'@ on comparisons always returns @EQ@. Without
          -- newtypes this equals @'pure' ('pure' EQ)@.
          --
          -- @
          -- mempty :: Comparison a
          -- mempty = Comparison \_ _ -> EQ
          -- @
          Semigroup (Comparison a)
    Comparison a
    Semigroup (Comparison a) =>
    Comparison a
    -> (Comparison a -> Comparison a -> Comparison a)
    -> ([Comparison a] -> Comparison a)
    -> Monoid (Comparison a)
    [Comparison a] -> Comparison a
    Comparison a -> Comparison a -> Comparison a
    forall a. Semigroup (Comparison a)
    forall a. Comparison a
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    forall a. [Comparison a] -> Comparison a
    forall a. Comparison a -> Comparison a -> Comparison a
    $cmempty :: forall a. Comparison a
    mempty :: Comparison a
    $cmappend :: forall a. Comparison a -> Comparison a -> Comparison a
    mappend :: Comparison a -> Comparison a -> Comparison a
    $cmconcat :: forall a. [Comparison a] -> Comparison a
    mconcat :: [Comparison a] -> Comparison a
    Monoid
        )

    -- | A 'Comparison' is a 'Contravariant' 'Functor', because 'contramap' can
    -- apply its function argument to each input of the comparison function.
    instance Contravariant Comparison where
      contramap :: (a' -> a) -> (Comparison a -> Comparison a')
      contramap :: forall a' a. (a' -> a) -> Comparison a -> Comparison a'
    contramap a' -> a
    f (Comparison a -> a -> Ordering
    g) = (a' -> a' -> Ordering) -> Comparison a'
    forall a. (a -> a -> Ordering) -> Comparison a
    Comparison ((a -> a -> Ordering) -> (a' -> a) -> a' -> a' -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    on a -> a -> Ordering
    g a' -> a
    f)

    -- | Compare using 'compare'.
    defaultComparison :: Ord a => Comparison a
    defaultComparison :: forall a. Ord a => Comparison a
    defaultComparison = (a -> a -> Ordering) -> Comparison a
    forall a. (a -> a -> Ordering) -> Comparison a
    Comparison a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare

    -- | This data type represents an equivalence relation.
    --
    -- Equivalence relations are expected to satisfy three laws:
    --
    -- [Reflexivity]:  @'getEquivalence' f a a = True@
    -- [Symmetry]:     @'getEquivalence' f a b = 'getEquivalence' f b a@
    -- [Transitivity]:
    --    If @'getEquivalence' f a b@ and @'getEquivalence' f b c@ are both 'True'
    --    then so is @'getEquivalence' f a c@.
    --
    -- The types alone do not enforce these laws, so you'll have to check them
    -- yourself.
    newtype Equivalence a = Equivalence { forall a. Equivalence a -> a -> a -> Bool
    getEquivalence :: a -> a -> Bool }
      deriving
        ( -- | @('<>')@ on equivalences uses logical conjunction @('&&')@
          -- on the results. Without newtypes this equals @'liftA2'
          -- ('liftA2' (&&))@.
          --
          -- @
          -- (<>) :: Equivalence a -> Equivalence a -> Equivalence a
          -- Equivalence equiv <> Equivalence equiv' = Equivalence \a b ->
          --   equiv a b && equiv' a b
          -- @
          NonEmpty (Equivalence a) -> Equivalence a
    Equivalence a -> Equivalence a -> Equivalence a
    (Equivalence a -> Equivalence a -> Equivalence a)
    -> (NonEmpty (Equivalence a) -> Equivalence a)
    -> (forall b. Integral b => b -> Equivalence a -> Equivalence a)
    -> Semigroup (Equivalence a)
    forall b. Integral b => b -> Equivalence a -> Equivalence a
    forall a. NonEmpty (Equivalence a) -> Equivalence a
    forall a. Equivalence a -> Equivalence a -> Equivalence a
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    forall a b. Integral b => b -> Equivalence a -> Equivalence a
    $c<> :: forall a. Equivalence a -> Equivalence a -> Equivalence a
    <> :: Equivalence a -> Equivalence a -> Equivalence a
    $csconcat :: forall a. NonEmpty (Equivalence a) -> Equivalence a
    sconcat :: NonEmpty (Equivalence a) -> Equivalence a
    $cstimes :: forall a b. Integral b => b -> Equivalence a -> Equivalence a
    stimes :: forall b. Integral b => b -> Equivalence a -> Equivalence a
    Semigroup
        , -- | @'mempty'@ on equivalences always returns @True@. Without
          -- newtypes this equals @'pure' ('pure' True)@.
          --
          -- @
          -- mempty :: Equivalence a
          -- mempty = Equivalence \_ _ -> True
          -- @
          Semigroup (Equivalence a)
    Equivalence a
    Semigroup (Equivalence a) =>
    Equivalence a
    -> (Equivalence a -> Equivalence a -> Equivalence a)
    -> ([Equivalence a] -> Equivalence a)
    -> Monoid (Equivalence a)
    [Equivalence a] -> Equivalence a
    Equivalence a -> Equivalence a -> Equivalence a
    forall a. Semigroup (Equivalence a)
    forall a. Equivalence a
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    forall a. [Equivalence a] -> Equivalence a
    forall a. Equivalence a -> Equivalence a -> Equivalence a
    $cmempty :: forall a. Equivalence a
    mempty :: Equivalence a
    $cmappend :: forall a. Equivalence a -> Equivalence a -> Equivalence a
    mappend :: Equivalence a -> Equivalence a -> Equivalence a
    $cmconcat :: forall a. [Equivalence a] -> Equivalence a
    mconcat :: [Equivalence a] -> Equivalence a
    Monoid
        )
      via a -> a -> All

    -- | Equivalence relations are 'Contravariant', because you can
    -- apply the contramapped function to each input to the equivalence
    -- relation.
    instance Contravariant Equivalence where
      contramap :: (a' -> a) -> (Equivalence a -> Equivalence a')
      contramap :: forall a' a. (a' -> a) -> Equivalence a -> Equivalence a'
    contramap a' -> a
    f (Equivalence a -> a -> Bool
    g) = (a' -> a' -> Bool) -> Equivalence a'
    forall a. (a -> a -> Bool) -> Equivalence a
    Equivalence ((a -> a -> Bool) -> (a' -> a) -> a' -> a' -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    on a -> a -> Bool
    g a' -> a
    f)

    -- | Check for equivalence with '=='.
    --
    -- Note: The instances for 'Double' and 'Float' violate reflexivity for @NaN@.
    defaultEquivalence :: Eq a => Equivalence a
    defaultEquivalence :: forall a. Eq a => Equivalence a
    defaultEquivalence = (a -> a -> Bool) -> Equivalence a
    forall a. (a -> a -> Bool) -> Equivalence a
    Equivalence a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    (==)

    comparisonEquivalence :: Comparison a -> Equivalence a
    comparisonEquivalence :: forall a. Comparison a -> Equivalence a
    comparisonEquivalence (Comparison a -> a -> Ordering
    p) = (a -> a -> Bool) -> Equivalence a
    forall a. (a -> a -> Bool) -> Equivalence a
    Equivalence ((a -> a -> Bool) -> Equivalence a)
    -> (a -> a -> Bool) -> Equivalence a
    forall a b. (a -> b) -> a -> b
    $ \a
    a a
    b -> a -> a -> Ordering
    p a
    a a
    b Ordering -> Ordering -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ordering
    EQ

    -- | Dual function arrows.
    newtype Op a b = Op { forall a b. Op a b -> b -> a
    getOp :: b -> a }
      deriving
      newtype
        ( -- | @('<>') \@(Op a b)@ without newtypes is @('<>') \@(b->a)@ =
          -- @liftA2 ('<>')@. This lifts the 'Semigroup' operation
          -- @('<>')@ over the output of @a@.
          --
          -- @
          -- (<>) :: Op a b -> Op a b -> Op a b
          -- Op f <> Op g = Op \a -> f a <> g a
          -- @
          NonEmpty (Op a b) -> Op a b
    Op a b -> Op a b -> Op a b
    (Op a b -> Op a b -> Op a b)
    -> (NonEmpty (Op a b) -> Op a b)
    -> (forall b. Integral b => b -> Op a b -> Op a b)
    -> Semigroup (Op a b)
    forall b. Integral b => b -> Op a b -> Op a b
    forall a.
    (a -> a -> a)
    -> (NonEmpty a -> a)
    -> (forall b. Integral b => b -> a -> a)
    -> Semigroup a
    forall a b. Semigroup a => NonEmpty (Op a b) -> Op a b
    forall a b. Semigroup a => Op a b -> Op a b -> Op a b
    forall a b b. (Semigroup a, Integral b) => b -> Op a b -> Op a b
    $c<> :: forall a b. Semigroup a => Op a b -> Op a b -> Op a b
    <> :: Op a b -> Op a b -> Op a b
    $csconcat :: forall a b. Semigroup a => NonEmpty (Op a b) -> Op a b
    sconcat :: NonEmpty (Op a b) -> Op a b
    $cstimes :: forall a b b. (Semigroup a, Integral b) => b -> Op a b -> Op a b
    stimes :: forall b. Integral b => b -> Op a b -> Op a b
    Semigroup
        , -- | @'mempty' \@(Op a b)@ without newtypes is @mempty \@(b->a)@
          -- = @\_ -> mempty@.
          --
          -- @
          -- mempty :: Op a b
          -- mempty = Op \_ -> mempty
          -- @
          Semigroup (Op a b)
    Op a b
    Semigroup (Op a b) =>
    Op a b
    -> (Op a b -> Op a b -> Op a b)
    -> ([Op a b] -> Op a b)
    -> Monoid (Op a b)
    [Op a b] -> Op a b
    Op a b -> Op a b -> Op a b
    forall a.
    Semigroup a =>
    a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
    forall a b. Monoid a => Semigroup (Op a b)
    forall a b. Monoid a => Op a b
    forall a b. Monoid a => [Op a b] -> Op a b
    forall a b. Monoid a => Op a b -> Op a b -> Op a b
    $cmempty :: forall a b. Monoid a => Op a b
    mempty :: Op a b
    $cmappend :: forall a b. Monoid a => Op a b -> Op a b -> Op a b
    mappend :: Op a b -> Op a b -> Op a b
    $cmconcat :: forall a b. Monoid a => [Op a b] -> Op a b
    mconcat :: [Op a b] -> Op a b
    Monoid
        )

    instance Category Op where
      id :: Op a a
      id :: forall a. Op a a
    id = (a -> a) -> Op a a
    forall a b. (b -> a) -> Op a b
    Op a -> a
    forall a. a -> a
    forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
    id

      (.) :: Op b c -> Op a b -> Op a c
      Op c -> b
    f . :: forall b c a. Op b c -> Op a b -> Op a c
    . Op b -> a
    g = (c -> a) -> Op a c
    forall a b. (b -> a) -> Op a b
    Op (b -> a
    g (b -> a) -> (c -> b) -> c -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . c -> b
    f)

    instance Contravariant (Op a) where
      contramap :: (b' -> b) -> (Op a b -> Op a b')
      contramap :: forall a' a. (a' -> a) -> Op a a -> Op a a'
    contramap b' -> b
    f Op a b
    g = (b' -> a) -> Op a b'
    forall a b. (b -> a) -> Op a b
    Op (Op a b -> b -> a
    forall a b. Op a b -> b -> a
    getOp Op a b
    g (b -> a) -> (b' -> b) -> b' -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b' -> b
    f)

    instance Num a => Num (Op a b) where
      Op b -> a
    f + :: Op a b -> Op a b -> Op a b
    + Op b -> a
    g = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> b -> a
    f b
    a a -> a -> a
    forall a. Num a => a -> a -> a
    + b -> a
    g b
    a
      Op b -> a
    f * :: Op a b -> Op a b -> Op a b
    * Op b -> a
    g = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> b -> a
    f b
    a a -> a -> a
    forall a. Num a => a -> a -> a
    * b -> a
    g b
    a
      Op b -> a
    f - :: Op a b -> Op a b -> Op a b
    - Op b -> a
    g = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> b -> a
    f b
    a a -> a -> a
    forall a. Num a => a -> a -> a
    - b -> a
    g b
    a
      abs :: Op a b -> Op a b
    abs (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Num a => a -> a
    abs (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      signum :: Op a b -> Op a b
    signum (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Num a => a -> a
    signum (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      fromInteger :: Integer -> Op a b
    fromInteger = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (Integer -> b -> a) -> Integer -> Op a b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> b -> a
    forall a b. a -> b -> a
    const (a -> b -> a) -> (Integer -> a) -> Integer -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Integer -> a
    forall a. Num a => Integer -> a
    fromInteger

    instance Fractional a => Fractional (Op a b) where
      Op b -> a
    f / :: Op a b -> Op a b -> Op a b
    / Op b -> a
    g = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> b -> a
    f b
    a a -> a -> a
    forall a. Fractional a => a -> a -> a
    / b -> a
    g b
    a
      recip :: Op a b -> Op a b
    recip (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Fractional a => a -> a
    recip (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      fromRational :: Rational -> Op a b
    fromRational = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (Rational -> b -> a) -> Rational -> Op a b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . a -> b -> a
    forall a b. a -> b -> a
    const (a -> b -> a) -> (Rational -> a) -> Rational -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Rational -> a
    forall a. Fractional a => Rational -> a
    fromRational

    instance Floating a => Floating (Op a b) where
      pi :: Op a b
    pi = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> b -> a
    forall a b. a -> b -> a
    const a
    forall a. Floating a => a
    pi
      exp :: Op a b -> Op a b
    exp (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    exp (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      sqrt :: Op a b -> Op a b
    sqrt (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    sqrt (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      log :: Op a b -> Op a b
    log (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    log (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      sin :: Op a b -> Op a b
    sin (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    sin (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      tan :: Op a b -> Op a b
    tan (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    tan (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      cos :: Op a b -> Op a b
    cos (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    cos (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      asin :: Op a b -> Op a b
    asin (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    asin (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      atan :: Op a b -> Op a b
    atan (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    atan (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      acos :: Op a b -> Op a b
    acos (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    acos (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      sinh :: Op a b -> Op a b
    sinh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    sinh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      tanh :: Op a b -> Op a b
    tanh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    tanh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      cosh :: Op a b -> Op a b
    cosh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    cosh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      asinh :: Op a b -> Op a b
    asinh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    asinh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      atanh :: Op a b -> Op a b
    atanh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    atanh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      acosh :: Op a b -> Op a b
    acosh (Op b -> a
    f) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ a -> a
    forall a. Floating a => a -> a
    acosh (a -> a) -> (b -> a) -> b -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . b -> a
    f
      Op b -> a
    f ** :: Op a b -> Op a b -> Op a b
    ** Op b -> a
    g = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> b -> a
    f b
    a a -> a -> a
    forall a. Floating a => a -> a -> a
    ** b -> a
    g b
    a
      logBase :: Op a b -> Op a b -> Op a b
    logBase (Op b -> a
    f) (Op b -> a
    g) = (b -> a) -> Op a b
    forall a b. (b -> a) -> Op a b
    Op ((b -> a) -> Op a b) -> (b -> a) -> Op a b
    forall a b. (a -> b) -> a -> b
    $ \b
    a -> a -> a -> a
    forall a. Floating a => a -> a -> a
    logBase (b -> a
    f b
    a) (b -> a
    g b
    a)