{-# LANGUAGE FlexibleContexts    #-}
{-# OPTIONS_HADDOCK not-home     #-}

-- |
-- Module      : Prelude.Backprop.Num
-- Copyright   : (c) Justin Le 2023
-- License     : BSD3
--
-- Maintainer  : justin@jle.im
-- Stability   : experimental
-- Portability : non-portable
--
-- Provides the exact same API as "Prelude.Backprop", except requiring
-- 'Num' instances for all types involved instead of 'Backprop' instances.
--
-- @since 0.2.0.0

module Prelude.Backprop.Num (
  -- * Foldable and Traversable
    sum
  , product
  , length
  , minimum
  , maximum
  , traverse
  , toList
  , mapAccumL
  , mapAccumR
  , foldr, foldl'
  -- * Functor and Applicative
  , fmap, fmapConst
  , (<$>), (<$), ($>)
  , pure
  , liftA2
  , liftA3
  -- * Numeric
  , fromIntegral
  , realToFrac
  , round
  , fromIntegral'
  -- * Misc
  , E.coerce
  ) where

import           Numeric.Backprop.Num
import           Prelude                   (Num(..), Fractional(..), Ord(..), Functor, Foldable, Traversable, Applicative)
import qualified Numeric.Backprop.Explicit as E
import qualified Prelude                   as P
import qualified Prelude.Backprop.Explicit as E

-- | 'Prelude.Backprop.sum', but with 'Num' constraints instead of
-- 'Backprop' constraints.
sum :: (Foldable t, Functor t, Num (t a), Num a, Reifies s W)
    => BVar s (t a)
    -> BVar s a
sum :: forall (t :: * -> *) a s.
(Foldable t, Functor t, Num (t a), Num a, Reifies s W) =>
BVar s (t a) -> BVar s a
sum = forall (t :: * -> *) a s.
(Foldable t, Functor t, Num a, Reifies s W) =>
AddFunc (t a) -> BVar s (t a) -> BVar s a
E.sum forall a. Num a => AddFunc a
E.afNum
{-# INLINE sum #-}

-- | 'Prelude.Backprop.pure', but with 'Num' constraints instead of
-- 'Backprop' constraints.
pure
    :: (Foldable t, Applicative t, Num a, Reifies s W)
    => BVar s a
    -> BVar s (t a)
pure :: forall (t :: * -> *) a s.
(Foldable t, Applicative t, Num a, Reifies s W) =>
BVar s a -> BVar s (t a)
pure = forall (t :: * -> *) s a.
(Foldable t, Applicative t, Reifies s W) =>
AddFunc a -> ZeroFunc a -> BVar s a -> BVar s (t a)
E.pure forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE pure #-}

-- | 'Prelude.Backprop.product', but with 'Num' constraints instead of
-- 'Backprop' constraints.
product
    :: (Foldable t, Functor t, Num (t a), Fractional a, Reifies s W)
    => BVar s (t a)
    -> BVar s a
product :: forall (t :: * -> *) a s.
(Foldable t, Functor t, Num (t a), Fractional a, Reifies s W) =>
BVar s (t a) -> BVar s a
product = forall (t :: * -> *) a s.
(Foldable t, Functor t, Fractional a, Reifies s W) =>
AddFunc (t a) -> BVar s (t a) -> BVar s a
E.product forall a. Num a => AddFunc a
E.afNum
{-# INLINE product #-}

-- | 'Prelude.Backprop.length', but with 'Num' constraints instead of
-- 'Backprop' constraints.
length
    :: (Foldable t, Num (t a), Num b, Reifies s W)
    => BVar s (t a)
    -> BVar s b
length :: forall (t :: * -> *) a b s.
(Foldable t, Num (t a), Num b, Reifies s W) =>
BVar s (t a) -> BVar s b
length = forall (t :: * -> *) b s a.
(Foldable t, Num b, Reifies s W) =>
AddFunc (t a) -> ZeroFunc (t a) -> BVar s (t a) -> BVar s b
E.length forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE length #-}

-- | 'Prelude.Backprop.minimum', but with 'Num' constraints instead of
-- 'Backprop' constraints.
minimum
    :: (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)
    => BVar s (t a)
    -> BVar s a
minimum :: forall (t :: * -> *) a s.
(Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) =>
BVar s (t a) -> BVar s a
minimum = forall (t :: * -> *) a s.
(Foldable t, Functor t, Ord a, Reifies s W) =>
AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
E.minimum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE minimum #-}

-- | 'Prelude.Backprop.maximum', but with 'Num' constraints instead of
-- 'Backprop' constraints.
maximum
    :: (Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W)
    => BVar s (t a)
    -> BVar s a
maximum :: forall (t :: * -> *) a s.
(Foldable t, Functor t, Num a, Ord a, Num (t a), Reifies s W) =>
BVar s (t a) -> BVar s a
maximum = forall (t :: * -> *) a s.
(Foldable t, Functor t, Ord a, Reifies s W) =>
AddFunc (t a) -> ZeroFunc a -> BVar s (t a) -> BVar s a
E.maximum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE maximum #-}

-- | 'Prelude.Backprop.foldr', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.3.0
foldr
    :: (Traversable t, Num a, Reifies s W)
    => (BVar s a -> BVar s b -> BVar s b)
    -> BVar s b
    -> BVar s (t a)
    -> BVar s b
foldr :: forall (t :: * -> *) a s b.
(Traversable t, Num a, Reifies s W) =>
(BVar s a -> BVar s b -> BVar s b)
-> BVar s b -> BVar s (t a) -> BVar s b
foldr = forall (t :: * -> *) s a b.
(Traversable t, Reifies s W) =>
AddFunc a
-> ZeroFunc a
-> (BVar s a -> BVar s b -> BVar s b)
-> BVar s b
-> BVar s (t a)
-> BVar s b
E.foldr forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE foldr #-}

-- | 'Prelude.Backprop.foldl'', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.3.0
foldl'
    :: (Traversable t, Num a, Reifies s W)
    => (BVar s b -> BVar s a -> BVar s b)
    -> BVar s b
    -> BVar s (t a)
    -> BVar s b
foldl' :: forall (t :: * -> *) a s b.
(Traversable t, Num a, Reifies s W) =>
(BVar s b -> BVar s a -> BVar s b)
-> BVar s b -> BVar s (t a) -> BVar s b
foldl' = forall (t :: * -> *) s a b.
(Traversable t, Reifies s W) =>
AddFunc a
-> ZeroFunc a
-> (BVar s b -> BVar s a -> BVar s b)
-> BVar s b
-> BVar s (t a)
-> BVar s b
E.foldl' forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE foldl' #-}

-- | 'Prelude.Backprop.fmap', but with 'Num' constraints instead of
-- 'Backprop' constraints.
fmap
    :: (Traversable f, Num a, Num b, Reifies s W)
    => (BVar s a -> BVar s b)
    -> BVar s (f a)
    -> BVar s (f b)
fmap :: forall (f :: * -> *) a b s.
(Traversable f, Num a, Num b, Reifies s W) =>
(BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
fmap = forall (f :: * -> *) s a b.
(Traversable f, Reifies s W) =>
AddFunc a
-> AddFunc b
-> ZeroFunc a
-> ZeroFunc b
-> (BVar s a -> BVar s b)
-> BVar s (f a)
-> BVar s (f b)
E.fmap forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE fmap #-}

-- | 'Prelude.Backprop.fmapConst', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.4.0
fmapConst
    :: (Functor f, Foldable f, Num b, Num (f a), Reifies s W)
    => BVar s b
    -> BVar s (f a)
    -> BVar s (f b)
fmapConst :: forall (f :: * -> *) b a s.
(Functor f, Foldable f, Num b, Num (f a), Reifies s W) =>
BVar s b -> BVar s (f a) -> BVar s (f b)
fmapConst = forall (f :: * -> *) s a b.
(Functor f, Foldable f, Reifies s W) =>
AddFunc (f a)
-> AddFunc b
-> ZeroFunc (f a)
-> ZeroFunc b
-> BVar s b
-> BVar s (f a)
-> BVar s (f b)
E.fmapConst forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE fmapConst #-}

-- | Alias for 'fmap'.
(<$>)
    :: (Traversable f, Num a, Num b, Reifies s W)
    => (BVar s a -> BVar s b)
    -> BVar s (f a)
    -> BVar s (f b)
<$> :: forall (f :: * -> *) a b s.
(Traversable f, Num a, Num b, Reifies s W) =>
(BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
(<$>) = forall (f :: * -> *) a b s.
(Traversable f, Num a, Num b, Reifies s W) =>
(BVar s a -> BVar s b) -> BVar s (f a) -> BVar s (f b)
fmap
infixl 4 <$>
{-# INLINE (<$>) #-}

-- | Alias for 'fmapConst'.
--
-- @since 0.2.4.0
(<$)
    :: (Functor f, Foldable f, Num b, Num (f a), Reifies s W)
    => BVar s b
    -> BVar s (f a)
    -> BVar s (f b)
<$ :: forall (f :: * -> *) b a s.
(Functor f, Foldable f, Num b, Num (f a), Reifies s W) =>
BVar s b -> BVar s (f a) -> BVar s (f b)
(<$) = forall (f :: * -> *) b a s.
(Functor f, Foldable f, Num b, Num (f a), Reifies s W) =>
BVar s b -> BVar s (f a) -> BVar s (f b)
fmapConst
infixl 4 <$
{-# INLINE (<$) #-}

-- | Alias for @'flip' 'fmapConst'@.
--
-- @since 0.2.4.0
($>)
    :: (Functor f, Foldable f, Num b, Num (f a), Reifies s W)
    => BVar s (f a)
    -> BVar s b
    -> BVar s (f b)
BVar s (f a)
xs $> :: forall (f :: * -> *) b a s.
(Functor f, Foldable f, Num b, Num (f a), Reifies s W) =>
BVar s (f a) -> BVar s b -> BVar s (f b)
$> BVar s b
x = BVar s b
x forall (f :: * -> *) b a s.
(Functor f, Foldable f, Num b, Num (f a), Reifies s W) =>
BVar s b -> BVar s (f a) -> BVar s (f b)
<$ BVar s (f a)
xs
infixl 4 $>
{-# INLINE ($>) #-}

-- | 'Prelude.Backprop.traverse', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- See <https://hackage.haskell.org/package/vector-sized vector-sized> for
-- a fixed-length vector type with a very appropriate 'Num' instance!
traverse
    :: (Traversable t, Applicative f, Foldable f, Num a, Num b, Num (t b), Reifies s W)
    => (BVar s a -> f (BVar s b))
    -> BVar s (t a)
    -> BVar s (f (t b))
traverse :: forall (t :: * -> *) (f :: * -> *) a b s.
(Traversable t, Applicative f, Foldable f, Num a, Num b, Num (t b),
 Reifies s W) =>
(BVar s a -> f (BVar s b)) -> BVar s (t a) -> BVar s (f (t b))
traverse = forall (t :: * -> *) (f :: * -> *) s a b.
(Traversable t, Applicative f, Foldable f, Reifies s W) =>
AddFunc a
-> AddFunc b
-> AddFunc (t b)
-> ZeroFunc a
-> ZeroFunc b
-> (BVar s a -> f (BVar s b))
-> BVar s (t a)
-> BVar s (f (t b))
E.traverse forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE traverse #-}

-- | 'Prelude.Backprop.liftA2', but with 'Num' constraints instead of
-- 'Backprop' constraints.
liftA2
    :: ( Traversable f
       , Applicative f
       , Num a, Num b, Num c
       , Reifies s W
       )
    => (BVar s a -> BVar s b -> BVar s c)
    -> BVar s (f a)
    -> BVar s (f b)
    -> BVar s (f c)
liftA2 :: forall (f :: * -> *) a b c s.
(Traversable f, Applicative f, Num a, Num b, Num c, Reifies s W) =>
(BVar s a -> BVar s b -> BVar s c)
-> BVar s (f a) -> BVar s (f b) -> BVar s (f c)
liftA2 = forall (f :: * -> *) s a b c.
(Traversable f, Applicative f, Reifies s W) =>
AddFunc a
-> AddFunc b
-> AddFunc c
-> ZeroFunc a
-> ZeroFunc b
-> ZeroFunc c
-> (BVar s a -> BVar s b -> BVar s c)
-> BVar s (f a)
-> BVar s (f b)
-> BVar s (f c)
E.liftA2 forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE liftA2 #-}

-- | 'Prelude.Backprop.liftA3', but with 'Num' constraints instead of
-- 'Backprop' constraints.
liftA3
    :: ( Traversable f
       , Applicative f
       , Num a, Num b, Num c, Num d
       , Reifies s W
       )
    => (BVar s a -> BVar s b -> BVar s c -> BVar s d)
    -> BVar s (f a)
    -> BVar s (f b)
    -> BVar s (f c)
    -> BVar s (f d)
liftA3 :: forall (f :: * -> *) a b c d s.
(Traversable f, Applicative f, Num a, Num b, Num c, Num d,
 Reifies s W) =>
(BVar s a -> BVar s b -> BVar s c -> BVar s d)
-> BVar s (f a) -> BVar s (f b) -> BVar s (f c) -> BVar s (f d)
liftA3 = forall (f :: * -> *) s a b c d.
(Traversable f, Applicative f, Reifies s W) =>
AddFunc a
-> AddFunc b
-> AddFunc c
-> AddFunc d
-> ZeroFunc a
-> ZeroFunc b
-> ZeroFunc c
-> ZeroFunc d
-> (BVar s a -> BVar s b -> BVar s c -> BVar s d)
-> BVar s (f a)
-> BVar s (f b)
-> BVar s (f c)
-> BVar s (f d)
E.liftA3 forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum
                  forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE liftA3 #-}

-- | 'Prelude.Backprop.fromIntegral', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.1.0
fromIntegral
    :: (P.Integral a, P.Integral b, Reifies s W)
    => BVar s a
    -> BVar s b
fromIntegral :: forall a b s.
(Integral a, Integral b, Reifies s W) =>
BVar s a -> BVar s b
fromIntegral = forall a b s.
(Integral a, Integral b, Reifies s W) =>
AddFunc a -> BVar s a -> BVar s b
E.fromIntegral forall a. Num a => AddFunc a
E.afNum
{-# INLINE fromIntegral #-}

-- | 'Prelude.Backprop.realToFrac', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.1.0
realToFrac
    :: (Fractional a, P.Real a, Fractional b, P.Real b, Reifies s W)
    => BVar s a
    -> BVar s b
realToFrac :: forall a b s.
(Fractional a, Real a, Fractional b, Real b, Reifies s W) =>
BVar s a -> BVar s b
realToFrac = forall a b s.
(Fractional a, Real a, Fractional b, Real b, Reifies s W) =>
AddFunc a -> BVar s a -> BVar s b
E.realToFrac forall a. Num a => AddFunc a
E.afNum
{-# INLINE realToFrac #-}

-- | 'Prelude.Backprop.round', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.3.0
round
    :: (P.RealFrac a, P.Integral b, Reifies s W)
    => BVar s a
    -> BVar s b
round :: forall a b s.
(RealFrac a, Integral b, Reifies s W) =>
BVar s a -> BVar s b
round = forall a b s.
(RealFrac a, Integral b, Reifies s W) =>
AddFunc a -> BVar s a -> BVar s b
E.round forall a. Num a => AddFunc a
E.afNum
{-# INLINE round #-}

-- | 'Prelude.Backprop.fromIntegral'', but with 'Num' constraints instead
-- of 'Backprop' constraints.
--
-- @since 0.2.3.0
fromIntegral'
    :: (P.Integral a, P.RealFrac b, Reifies s W)
    => BVar s a
    -> BVar s b
fromIntegral' :: forall a b s.
(Integral a, RealFrac b, Reifies s W) =>
BVar s a -> BVar s b
fromIntegral' = forall a b s.
(Integral a, RealFrac b, Reifies s W) =>
AddFunc a -> BVar s a -> BVar s b
E.fromIntegral' forall a. Num a => AddFunc a
E.afNum
{-# INLINE fromIntegral' #-}

-- | 'Prelude.Backprop.toList', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- @since 0.2.2.0
toList
    :: (Traversable t, Num a, Reifies s W)
    => BVar s (t a)
    -> [BVar s a]
toList :: forall (t :: * -> *) a s.
(Traversable t, Num a, Reifies s W) =>
BVar s (t a) -> [BVar s a]
toList = forall (t :: * -> *) s a.
(Traversable t, Reifies s W) =>
AddFunc a -> ZeroFunc a -> BVar s (t a) -> [BVar s a]
E.toList forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE toList #-}

-- | 'Prelude.Backprop.mapAccumL', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- Prior to v0.2.3, required a 'Num' constraint on @t b@.
--
-- @since 0.2.2.0
mapAccumL
    :: (Traversable t, Num b, Num c, Reifies s W)
    => (BVar s a -> BVar s b -> (BVar s a, BVar s c))
    -> BVar s a
    -> BVar s (t b)
    -> (BVar s a, BVar s (t c))
mapAccumL :: forall (t :: * -> *) b c s a.
(Traversable t, Num b, Num c, Reifies s W) =>
(BVar s a -> BVar s b -> (BVar s a, BVar s c))
-> BVar s a -> BVar s (t b) -> (BVar s a, BVar s (t c))
mapAccumL = forall (t :: * -> *) s b c a.
(Traversable t, Reifies s W) =>
AddFunc b
-> AddFunc c
-> ZeroFunc b
-> ZeroFunc c
-> (BVar s a -> BVar s b -> (BVar s a, BVar s c))
-> BVar s a
-> BVar s (t b)
-> (BVar s a, BVar s (t c))
E.mapAccumL forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE mapAccumL #-}

-- | 'Prelude.Backprop.mapAccumR', but with 'Num' constraints instead of
-- 'Backprop' constraints.
--
-- Prior to v0.2.3, required a 'Num' constraint on @t b@.
--
-- @since 0.2.2.0
mapAccumR
    :: (Traversable t, Num b, Num c, Reifies s W)
    => (BVar s a -> BVar s b -> (BVar s a, BVar s c))
    -> BVar s a
    -> BVar s (t b)
    -> (BVar s a, BVar s (t c))
mapAccumR :: forall (t :: * -> *) b c s a.
(Traversable t, Num b, Num c, Reifies s W) =>
(BVar s a -> BVar s b -> (BVar s a, BVar s c))
-> BVar s a -> BVar s (t b) -> (BVar s a, BVar s (t c))
mapAccumR = forall (t :: * -> *) s b c a.
(Traversable t, Reifies s W) =>
AddFunc b
-> AddFunc c
-> ZeroFunc b
-> ZeroFunc c
-> (BVar s a -> BVar s b -> (BVar s a, BVar s c))
-> BVar s a
-> BVar s (t b)
-> (BVar s a, BVar s (t c))
E.mapAccumR forall a. Num a => AddFunc a
E.afNum forall a. Num a => AddFunc a
E.afNum forall a. Num a => ZeroFunc a
E.zfNum forall a. Num a => ZeroFunc a
E.zfNum
{-# INLINE mapAccumR #-}