{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
----------------------------------------------------------------
--                                                    2021.10.17
-- |
-- Module      :  Data.Function.Pointless
-- Copyright   :  Copyright (c) 2009--2021 wren gayle romano
-- License     :  BSD
-- Maintainer  :  wren@cpan.org
-- Stability   :  provisional
-- Portability :  Haskell98
--
-- Pointless fun :)
----------------------------------------------------------------
module Data.Function.Pointless
    (
    -- * Multicomposition
    -- | Based on <http://matt.immute.net/content/pointless-fun>.
    -- These combinators allow you to easily modify the types of a
    -- many-argument function with syntax that looks like giving
    -- type signatures. For example,
    --
    -- > foo    :: A -> B -> C
    -- >
    -- > albert :: X -> A
    -- > beth   :: Y -> B
    -- > carol  :: C -> Z
    -- >
    -- > bar :: X -> Y -> Z
    -- > bar = foo $:: albert ~> beth ~> carol
      ($::), (~>), (!~>)

    -- * Composition for arity 2
    , (.:), (.^)

    -- * Strict composition
    , (.!)
    ) where
----------------------------------------------------------------
----------------------------------------------------------------
{- TODO: actually put this in.
-- Note: @pl had nothing to do with the invention of this combinator. I constructed it by hand after noticing a common pattern. -- Cale

swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d
swing = flip . (. flip id)
swing f = flip (f . runCont . return)
swing f c a = f ($ a) c

-- Some examples of use:

swing map :: forall a b. [a -> b] -> a -> [b]
swing any :: forall a. [a -> Bool] -> a -> Bool
swing foldr :: forall a b. b -> a -> [a -> b -> b] -> b
swing zipWith :: forall a b c. [a -> b -> c] -> a -> [b] -> [c]
swing find :: forall a. [a -> Bool] -> a -> Maybe (a -> Bool)
   -- applies each of the predicates to the given value, returning the first predicate which succeeds, if any
swing partition :: forall a. [a -> Bool] -> a -> ([a -> Bool], [a -> Bool])
-}
----------------------------------------------------------------


-- | Lift a function for multicomposition. This is like the @::@
-- of a type signature.

($::) :: (a -> b) -> ((a -> b) -> (c -> d)) -> (c -> d)
$:: :: (a -> b) -> ((a -> b) -> c -> d) -> c -> d
($::) = (((a -> b) -> c -> d) -> (a -> b) -> c -> d)
-> (a -> b) -> ((a -> b) -> c -> d) -> c -> d
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((a -> b) -> c -> d) -> (a -> b) -> c -> d
forall a b. (a -> b) -> a -> b
($)
{-# INLINE ($::) #-}
infixl 1 $::


-- | Multicompose a function on the appropriate argument. This is
-- like the @->@ arrows in a type signature.

(~>)  :: (a -> b) -> (c -> d) -> ((b -> c) -> (a -> d))
a -> b
f ~> :: (a -> b) -> (c -> d) -> (b -> c) -> a -> d
~> c -> d
g = ((b -> d) -> (a -> b) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) ((b -> d) -> a -> d) -> ((b -> c) -> b -> d) -> (b -> c) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> d
g (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)
{-# INLINE (~>) #-}
infixr 2 ~>


-- | Multicompose a function on the appropriate argument, calling
-- the left function eagerly. That is, the resulting function will
-- be strict in @a@ if the left argument is strict in @a@ (assuming
-- the final function of the multicomposition, the one applied to
-- the return value, is also strict).

(!~>)  :: (a -> b) -> (c -> d) -> ((b -> c) -> (a -> d))
a -> b
f !~> :: (a -> b) -> (c -> d) -> (b -> c) -> a -> d
!~> c -> d
g = ((b -> d) -> (a -> b) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
.! a -> b
f) ((b -> d) -> a -> d) -> ((b -> c) -> b -> d) -> (b -> c) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> d
g (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
.)
{-# INLINE (!~>) #-}
infixr 2 !~>


----------------------------------------------------------------
-- | Binary composition: pass two args to the right argument before
-- composing.
--
-- > (f .: g) x y = f (g x y)
--
-- or,
--
-- > f .: g = curry (f . uncurry g)
--
-- This is the same as the common idiom @(f .) . g@ but more easily
-- extended to multiple uses, due to the fixity declaration.

(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
.: :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = ((b -> c) -> b -> d) -> (a -> b -> c) -> a -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (((b -> c) -> b -> d) -> (a -> b -> c) -> a -> b -> d)
-> ((c -> d) -> (b -> c) -> b -> d)
-> (c -> d)
-> (a -> b -> c)
-> a
-> b
-> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)
{-# INLINE (.:) #-}
infixl 8 .:


-- | Secondary composition: compose the right argument on the second
-- arg of the left argument.
--
-- > (f .^ g) x y = f x (g y)

(.^) :: (a -> c -> d) -> (b -> c) -> (a -> b -> d)
.^ :: (a -> c -> d) -> (b -> c) -> a -> b -> d
(.^) = (b -> a -> d) -> a -> b -> d
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((b -> a -> d) -> a -> b -> d)
-> ((a -> c -> d) -> (b -> c) -> b -> a -> d)
-> (a -> c -> d)
-> (b -> c)
-> a
-> b
-> d
forall c d a b. (c -> d) -> (a -> b -> c) -> a -> b -> d
.: (c -> a -> d) -> (b -> c) -> b -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ((c -> a -> d) -> (b -> c) -> b -> a -> d)
-> ((a -> c -> d) -> c -> a -> d)
-> (a -> c -> d)
-> (b -> c)
-> b
-> a
-> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> c -> d) -> c -> a -> d
forall a b c. (a -> b -> c) -> b -> a -> c
flip
{-# INLINE (.^) #-}
infix 9 .^


-- | Function composition which calls the right-hand function
-- eagerly; i.e., making the left-hand function strict in its first
-- argument.
--
-- > (f .! g) x = f $! g x
--
-- This defines the composition for the sub-category of strict
-- Haskell functions. If the 'Functor' class were parameterized by
-- the domain and codomain categories (e.g., a regular @Functor f@
-- would be @CFunctor (->) (->) f@ instead) then this would allow
-- us to define functors @CFunctor (->) (!->) f@ where
-- @fmap f . fmap g = fmap (f .! g)@.

(.!) :: (b -> c) -> (a -> b) -> a -> c
.! :: (b -> c) -> (a -> b) -> a -> c
(.!) = (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) ((b -> c) -> (a -> b) -> a -> c)
-> ((b -> c) -> b -> c) -> (b -> c) -> (a -> b) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> c) -> b -> c
forall a b. (a -> b) -> a -> b
($!)
{-# INLINE (.!) #-}
infixr 9 .!
-- For some reason this definition is significantly faster than the
-- pointful version in the documentation. Even after INLINE. Who knew?
--
-- cf vs @($!) .: (.)@ == @\f g x -> f . g $! x@ which stictifies
-- the first argument of RH-function. However, this doesn't behave
-- the way you may think it should; i.e., it isn't compositional
-- in the way you think it should be.

----------------------------------------------------------------
----------------------------------------------------------- fin.