{-# LANGUAGE CPP  #-}
{-# LANGUAGE Safe #-}

{- |
Module                  : Relude.Functor.Fmap
Copyright               : (c) 2016 Stephen Diehl
                          (c) 2016-2018 Serokell
                          (c) 2018-2023 Kowainik
SPDX-License-Identifier : MIT
Maintainer              : Kowainik <xrom.xkov@gmail.com>
Stability               : Stable
Portability             : Portable

This module contains useful functions to work with 'Functor' type class.
-}

module Relude.Functor.Fmap
    ( (<<$>>)
    , (<&>)
    , flap
    , (??)
    ) where

import Relude.Function ((.))
import Relude.Functor.Reexport (Functor (..))

import Data.Functor ((<$>))
#if MIN_VERSION_base(4,11,0)
import Data.Functor ((<&>))
#else


{- | Flipped version of '<$>'.

@
f <$> a = a <&> f
@
-}
infixl 1 <&>
(<&>) :: Functor f => f a -> (a -> b) -> f b
as <&> f = f <$> as
{-# INLINE (<&>) #-}
#endif

-- $setup
-- >>> import Relude.Monad (Maybe (..))
-- >>> import Relude.List ((++))
-- >>> import Relude.Numeric (negate, (*), (+))

{- | Alias for @fmap . fmap@. Convenient to work with two nested 'Functor's.

>>> negate <<$>> Just [1,2,3]
Just [-1,-2,-3]
-}
infixl 4 <<$>>
(<<$>>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
<<$>> :: forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
(<<$>>) = (g a -> g b) -> f (g a) -> f (g b)
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((g a -> g b) -> f (g a) -> f (g b))
-> ((a -> b) -> g a -> g b) -> (a -> b) -> f (g a) -> f (g b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> g a -> g b
forall a b. (a -> b) -> g a -> g b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
{-# INLINE (<<$>>) #-}

{- | Takes a function in a 'Functor' context and applies it to a normal value.

>>> flap (++) "relude" "P"
"Prelude"

@since 0.3.0
-}
flap :: Functor f => f (a -> b) -> a -> f b
flap :: forall (f :: * -> *) a b. Functor f => f (a -> b) -> a -> f b
flap f (a -> b)
ff a
x = (\a -> b
f -> a -> b
f a
x) ((a -> b) -> b) -> f (a -> b) -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f (a -> b)
ff
{-# INLINE flap #-}

{- | Operator version of the 'flap' function.

>>> [(+2), (*3)] ?? 5
[7,15]

>>> Just (+3) ?? 5
Just 8

@since 0.3.0
-}
infixl 4 ??
(??) :: Functor f => f (a -> b) -> a -> f b
?? :: forall (f :: * -> *) a b. Functor f => f (a -> b) -> a -> f b
(??) = f (a -> b) -> a -> f b
forall (f :: * -> *) a b. Functor f => f (a -> b) -> a -> f b
flap
{-# INLINE (??) #-}