{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE Trustworthy #-}
-----------------------------------------------------------------------------

-- |

-- Copyright   :  (C) 2011-2015 Edward Kmett

-- License     :  BSD-style (see the file LICENSE)

--

-- Maintainer  :  Edward Kmett <ekmett@gmail.com>

-- Stability   :  provisional

-- Portability :  portable

--

----------------------------------------------------------------------------

module Data.Functor.Bind (
  -- * Functors

    Functor(..)
  , (<$>)     -- :: Functor f => (a -> b) -> f a -> f b

  , ( $>)     -- :: Functor f => f a -> b -> f b

  -- * Applyable functors

  , Apply(..)
  , (<..>)    -- :: Apply w => w a -> w (a -> b) -> w b

  , liftF3    -- :: Apply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d

  -- * Wrappers

  , WrappedApplicative(..)
  , MaybeApply(..)
  -- * Bindable functors

  , Bind(..)
  , gbind
  , (-<<)
  , (-<-)
  , (->-)
  , apDefault
  , returning
  ) where

import Data.Functor.Apply
import Data.Functor.Bind.Class
import GHC.Generics

-- | Generic '(>>-)'. Caveats:

--

--   1. Will not compile if @m@ is a sum type.

--   2. Will not compile if @m@ contains fields that do not mention its type variable.

--   3. Will not compile if @m@ contains fields where the type variable appears underneath the composition of type constructors (e.g., @f (g a)@).

--   4. May do redundant work, due to the nature of the 'Bind' instance for (':*:')

--

-- @since 5.3.8

gbind :: (Generic1 m, Bind (Rep1 m)) => m a -> (a -> m b) -> m b
gbind :: forall (m :: * -> *) a b.
(Generic1 m, Bind (Rep1 m)) =>
m a -> (a -> m b) -> m b
gbind m a
m a -> m b
f = forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 forall a b. (a -> b) -> a -> b
$ forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 m a
m forall (m :: * -> *) a b. Bind m => m a -> (a -> m b) -> m b
>>- (\a
a -> forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 forall a b. (a -> b) -> a -> b
$ a -> m b
f a
a)

infixr 1 -<<, -<-, ->-

(-<<) :: Bind m => (a -> m b) -> m a -> m b
-<< :: forall (m :: * -> *) a b. Bind m => (a -> m b) -> m a -> m b
(-<<) = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a b. Bind m => m a -> (a -> m b) -> m b
(>>-)

(->-) :: Bind m => (a -> m b) -> (b -> m c) -> a -> m c
a -> m b
f ->- :: forall (m :: * -> *) a b c.
Bind m =>
(a -> m b) -> (b -> m c) -> a -> m c
->- b -> m c
g = \a
a -> a -> m b
f a
a forall (m :: * -> *) a b. Bind m => m a -> (a -> m b) -> m b
>>- b -> m c
g

(-<-) :: Bind m => (b -> m c) -> (a -> m b) -> a -> m c
b -> m c
g -<- :: forall (m :: * -> *) b c a.
Bind m =>
(b -> m c) -> (a -> m b) -> a -> m c
-<- a -> m b
f = \a
a -> a -> m b
f a
a forall (m :: * -> *) a b. Bind m => m a -> (a -> m b) -> m b
>>- b -> m c
g