{-# LANGUAGE FlexibleInstances #-}

-- | Carrier injection for polymorphic differentiable models.
--
-- When a physical right-hand side is written once and polymorphic in a
-- numeric carrier, constants must be lifted into that carrier.  'Lit'
-- provides the overload: instantiating at 'Double' gives forward simulation;
-- instantiating at @'Diff' p 'Double' 'Double'@ gives reverse-mode
-- derivatives of every intermediate.
module Circuit.Diff.Carrier
  ( Lit (..),
  )
where

import Circuit.Diff.Circuit (Diff (..))
import Prelude

-- | Lift a numeric literal into the active carrier.
--
-- @
-- instance Lit Double where lit = id
-- instance Lit (Diff p Double Double) where lit c = Diff (const (c, const 0))
-- @
--
-- Every coefficient in a polymorphic model can be written @'lit' c@ once,
-- and resolves correctly under both simulation and differentiation.
class Lit a where
  lit :: Double -> a

instance Lit Double where
  lit :: Double -> Double
lit = Double -> Double
forall a. a -> a
id

instance Lit (Diff p Double Double) where
  lit :: Double -> Diff p Double Double
lit Double
c = (Double -> (Double, Double -> Double)) -> Diff p Double Double
forall k (p :: k) a b. (a -> (b, b -> a)) -> Diff p a b
Diff ((Double, Double -> Double) -> Double -> (Double, Double -> Double)
forall a b. a -> b -> a
const (Double
c, Double -> Double -> Double
forall a b. a -> b -> a
const Double
0))