{-# LANGUAGE CPP                   #-}
{-# LANGUAGE ConstraintKinds       #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds             #-}
{-# LANGUAGE RoleAnnotations       #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeApplications      #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE TypeOperators         #-}
{-# LANGUAGE UndecidableInstances  #-}
{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
#if defined(__HADDOCK__) || defined(__HADDOCK_VERSION__)
{-# OPTIONS_GHC -fno-warn-simplifiable-class-constraints #-}
#else
{-# OPTIONS_GHC -fplugin Data.Constraint.Deriving #-}
#endif
{-
This module contains all generic and specific instances for all backend
(implementation) types. Its hs-boot counterpart provides only generic instances
(that do not depend on BackendFamily).
Import this module only at the root of the module hierarchy, where the specific
implementation-dependent modules do not need to depend on it.
But do not forget to import this module in the places that will be imported by
the user (such as Numeric.DataFrame). So that the user can benefit from the
compile-time knowledge of the specific backend implementation.

By design the import chain is as follows:

NDI.Backend.Family.hs-boot            NDI.Backend.Family
         \                                   |
    NDI.Backend.hs-boot               NDI.Backend (instances only)
          \                                 /
     NDI.BackendI                          /
            \                             /
    Numeric.DataFrame.Type               /
                    \                   /
                     \                 /
                     Numeric.DataFrame

 -}
module Numeric.DataFrame.Internal.Backend
  ( Backend (..), BackendFamily, KnownBackend ()
  , inferKnownBackend, inferPrimElem
    -- * Auto-deriving instances
  , inferEq, inferOrd
  , inferProductOrder, inferPONonTransitive, inferPOPartial
  , inferBounded, inferNum
  , inferFractional, inferFloating
  , inferPrimBytes, inferPrimArray
  ) where


import Data.Constraint
import Data.Constraint.Deriving
import Data.Constraint.Unsafe
import Data.Kind                (Type)
import Unsafe.Coerce            (unsafeCoerce)

import           Numeric.DataFrame.Internal.PrimArray
import           Numeric.Dimensions
import           Numeric.PrimBytes
import           Numeric.ProductOrd
import qualified Numeric.ProductOrd.NonTransitive     as NonTransitive
import qualified Numeric.ProductOrd.Partial           as Partial

import           Numeric.DataFrame.Internal.Backend.Family (BackendFamily)
import qualified Numeric.DataFrame.Internal.Backend.Family as Impl (KnownBackend,
                                                                    inferBackendInstance,
                                                                    inferKnownBackend,
                                                                    inferPrimArray,
                                                                    inferPrimElem)


-- | Backend resolver:
--   Use this constraint to find any class instances defined for all DataFrame implementations,
--   e.g. @Num@, @PrimBytes@, etc.
class Impl.KnownBackend t ds (BackendFamily t ds)
   => KnownBackend (t :: Type) (ds :: [Nat])
instance Impl.KnownBackend t ds (BackendFamily t ds)
   => KnownBackend (t :: Type) (ds :: [Nat])

-- | A newtype wrapper for all DataFrame implementations.
--   I need two layers of wrappers to provide default overlappable instances to
--   all type classes using KnownBackend mechanics.
--   Type arguments are redundant here;
--   nevertheless, they improve readability of error messages.
newtype Backend (i :: Type) (t :: Type) (ds :: [Nat]) (backend :: Type)
    = Backend { Backend i t ds backend -> backend
_getBackend :: backend }
type role Backend phantom phantom phantom representational
type instance DeriveContext (Backend i t ds b) = b ~ BackendFamily t ds
-- When typechecker knows what the fourth parameter @b@ is, no instances overlap,
-- because @b@ is always always a concrete type.
-- The "dynamic instances" derived via ToInstance have to be incoherent,
-- because @BackendFamily t ds@ as a type family (before resolving it)
--  is no more concrete than just @b@.
{-# ANN type Backend (DeriveAll' NoOverlap ["KnownBackend"]) #-}



inferKnownBackend
  :: forall (t :: Type) (ds :: [Nat])
   . (PrimBytes t, Dimensions ds)
  => Dict (KnownBackend t ds)
inferKnownBackend :: Dict (KnownBackend t ds)
inferKnownBackend
  = case (PrimBytes t, Dimensions ds,
 BackendFamily t ds ~ BackendFamily t ds) =>
Dict (KnownBackend t ds (BackendFamily t ds))
forall t (ds :: [Nat]) b.
(PrimBytes t, Dimensions ds, b ~ BackendFamily t ds) =>
Dict (KnownBackend t ds b)
Impl.inferKnownBackend @t @ds @(BackendFamily t ds) of
      Dict (KnownBackend t ds (BackendFamily t ds))
Dict -> Dict (KnownBackend t ds)
forall (a :: Constraint). a => Dict a
Dict

inferPrimElem
  :: forall (t :: Type) (d :: Nat) (ds :: [Nat]) (i :: Type)
   . KnownBackend t (d ': ds)
  => Backend i t (d ': ds) (BackendFamily t (d ': ds)) -> Dict (PrimBytes t)
inferPrimElem :: Backend i t (d : ds) (BackendFamily t (d : ds))
-> Dict (PrimBytes t)
inferPrimElem = forall b.
(KnownBackend t (d : ds) b, b ~ BackendFamily t (d : ds)) =>
b -> Dict (PrimBytes t)
forall t (d :: Nat) (ds :: [Nat]) b.
(KnownBackend t (d : ds) b, b ~ BackendFamily t (d : ds)) =>
b -> Dict (PrimBytes t)
Impl.inferPrimElem @t @d @ds (BackendFamily t (d : ds) -> Dict (PrimBytes t))
-> (Backend i t (d : ds) (BackendFamily t (d : ds))
    -> BackendFamily t (d : ds))
-> Backend i t (d : ds) (BackendFamily t (d : ds))
-> Dict (PrimBytes t)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Backend i t (d : ds) (BackendFamily t (d : ds))
-> BackendFamily t (d : ds)
forall i t (ds :: [Nat]) backend. Backend i t ds backend -> backend
_getBackend



inferEq
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Eq t, Impl.KnownBackend t ds b)
  => Dict (Eq (Backend i t ds b))
inferEq :: Dict (Eq (Backend i t ds b))
inferEq
    = (Eq b :- Eq (Backend i t ds b))
-> Dict (Eq b) -> Dict (Eq (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Eq b :- Eq (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Eq b) -> Dict (Eq (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Eq b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Eq (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Eq b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Eq b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Eq b))
-> (b ~ BackendFamily t ds) :- Eq b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds) -> Dict (Eq (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds) -> Dict (Eq (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferOrd
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Ord t, Impl.KnownBackend t ds b)
  => Dict (Ord (Backend i t ds b))
inferOrd :: Dict (Ord (Backend i t ds b))
inferOrd
    = (Ord b :- Ord (Backend i t ds b))
-> Dict (Ord b) -> Dict (Ord (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Ord b :- Ord (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Ord b) -> Dict (Ord (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Ord b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Ord b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Ord b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Ord b))
-> (b ~ BackendFamily t ds) :- Ord b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds) -> Dict (Ord (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds) -> Dict (Ord (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferProductOrder
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Ord t, Impl.KnownBackend t ds b)
  => Dict (ProductOrder (Backend i t ds b))
inferProductOrder :: Dict (ProductOrder (Backend i t ds b))
inferProductOrder
    = (ProductOrder b :- ProductOrder (Backend i t ds b))
-> Dict (ProductOrder b) -> Dict (ProductOrder (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict ProductOrder b :- ProductOrder (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (ProductOrder b) -> Dict (ProductOrder (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (ProductOrder b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (ProductOrder (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- ProductOrder b)
-> Dict (b ~ BackendFamily t ds) -> Dict (ProductOrder b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (ProductOrder b))
-> (b ~ BackendFamily t ds) :- ProductOrder b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (ProductOrder (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (ProductOrder (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferPONonTransitive
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Ord t, Impl.KnownBackend t ds b)
  => Dict (Ord (NonTransitive.ProductOrd (Backend i t ds b)))
inferPONonTransitive :: Dict (Ord (ProductOrd (Backend i t ds b)))
inferPONonTransitive
    = (Ord (Backend i t ds b) :- Ord (ProductOrd (Backend i t ds b)))
-> Dict (Ord (Backend i t ds b))
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict ((Backend i t ds b -> ProductOrd (Backend i t ds b))
-> Ord (Backend i t ds b) :- Ord (ProductOrd (Backend i t ds b))
forall n o (t :: * -> Constraint).
Coercible n o =>
(o -> n) -> t o :- t n
unsafeDerive Backend i t ds b -> ProductOrd (Backend i t ds b)
forall a. a -> ProductOrd a
NonTransitive.ProductOrd)
    (Dict (Ord (Backend i t ds b))
 -> Dict (Ord (ProductOrd (Backend i t ds b))))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Ord (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ord b :- Ord (Backend i t ds b))
-> Dict (Ord b) -> Dict (Ord (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Ord b :- Ord (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Ord b) -> Dict (Ord (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Ord b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Ord b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Ord b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Ord b))
-> (b ~ BackendFamily t ds) :- Ord b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (Ord (ProductOrd (Backend i t ds b))))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferPOPartial
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Ord t, Impl.KnownBackend t ds b)
  => Dict (Ord (Partial.ProductOrd (Backend i t ds b)))
inferPOPartial :: Dict (Ord (ProductOrd (Backend i t ds b)))
inferPOPartial
    = (Ord (Backend i t ds b) :- Ord (ProductOrd (Backend i t ds b)))
-> Dict (Ord (Backend i t ds b))
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict ((Backend i t ds b -> ProductOrd (Backend i t ds b))
-> Ord (Backend i t ds b) :- Ord (ProductOrd (Backend i t ds b))
forall n o (t :: * -> Constraint).
Coercible n o =>
(o -> n) -> t o :- t n
unsafeDerive Backend i t ds b -> ProductOrd (Backend i t ds b)
forall a. a -> ProductOrd a
Partial.ProductOrd)
    (Dict (Ord (Backend i t ds b))
 -> Dict (Ord (ProductOrd (Backend i t ds b))))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Ord (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ord b :- Ord (Backend i t ds b))
-> Dict (Ord b) -> Dict (Ord (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Ord b :- Ord (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Ord b) -> Dict (Ord (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Ord b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Ord b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Ord b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Ord b))
-> (b ~ BackendFamily t ds) :- Ord b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (Ord (ProductOrd (Backend i t ds b))))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Ord (ProductOrd (Backend i t ds b)))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferBounded
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Bounded t, Impl.KnownBackend t ds b)
  => Dict (Bounded (Backend i t ds b))
inferBounded :: Dict (Bounded (Backend i t ds b))
inferBounded
    -- Here is an ugly trick:
    --  We don't have instance of @Bounded Float@ and @Bounded Double@.
    --  However, we want to have an instance @Bounded t => Bounded (Backend t ds b)@.
    --  Some specialized implementations (e.g. FloatX4) require explicit
    --    constraints @Bounded Float@ or @Bounded Double@.
    --  To satisfy these, I pull @Bounded t@ convincing the compiler that @t ~ Float@.
    --  This should work fine even if a user implements instances of Bounded for
    --    the floating types, because we know that @t ~ Float@ or @t ~ Double@
    --    automatically whenever this instance is called for these types.
  | Dict (Bounded Float)
Dict <- (case (Dict (t ~ t) -> Dict (t ~ Float)
forall a b. a -> b
unsafeCoerce ((t ~ t) => Dict (t ~ t)
forall (a :: Constraint). a => Dict a
Dict @(t ~ t)) :: Dict (t ~ Float)) of
               Dict (t ~ Float)
Dict -> Dict (Bounded Float)
forall (a :: Constraint). a => Dict a
Dict) :: Dict (Bounded Float)
  , Dict (Bounded Double)
Dict <- (case (Dict (t ~ t) -> Dict (t ~ Double)
forall a b. a -> b
unsafeCoerce ((t ~ t) => Dict (t ~ t)
forall (a :: Constraint). a => Dict a
Dict @(t ~ t)) :: Dict (t ~ Double)) of
               Dict (t ~ Double)
Dict -> Dict (Bounded Double)
forall (a :: Constraint). a => Dict a
Dict) :: Dict (Bounded Double)
    = (Bounded b :- Bounded (Backend i t ds b))
-> Dict (Bounded b) -> Dict (Bounded (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Bounded b :- Bounded (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Bounded b) -> Dict (Bounded (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Bounded b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Bounded (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Bounded b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Bounded b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Bounded b))
-> (b ~ BackendFamily t ds) :- Bounded b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (Bounded (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Bounded (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferNum
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Num t, Impl.KnownBackend t ds b)
  => Dict (Num (Backend i t ds b))
inferNum :: Dict (Num (Backend i t ds b))
inferNum
    = (Num b :- Num (Backend i t ds b))
-> Dict (Num b) -> Dict (Num (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Num b :- Num (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Num b) -> Dict (Num (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Num b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Num (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Num b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Num b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Num b))
-> (b ~ BackendFamily t ds) :- Num b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds) -> Dict (Num (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds) -> Dict (Num (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferFractional
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Fractional t, Impl.KnownBackend t ds b)
  => Dict (Fractional (Backend i t ds b))
inferFractional :: Dict (Fractional (Backend i t ds b))
inferFractional
    = (Fractional b :- Fractional (Backend i t ds b))
-> Dict (Fractional b) -> Dict (Fractional (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Fractional b :- Fractional (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Fractional b) -> Dict (Fractional (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Fractional b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Fractional (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Fractional b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Fractional b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Fractional b))
-> (b ~ BackendFamily t ds) :- Fractional b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (Fractional (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Fractional (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferFloating
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (Floating t, Impl.KnownBackend t ds b)
  => Dict (Floating (Backend i t ds b))
inferFloating :: Dict (Floating (Backend i t ds b))
inferFloating
    = (Floating b :- Floating (Backend i t ds b))
-> Dict (Floating b) -> Dict (Floating (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict Floating b :- Floating (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (Floating b) -> Dict (Floating (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (Floating b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Floating (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- Floating b)
-> Dict (b ~ BackendFamily t ds) -> Dict (Floating b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (Floating b))
-> (b ~ BackendFamily t ds) :- Floating b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (Floating (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (Floating (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined


inferPrimBytes
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (PrimBytes t, Dimensions ds, Impl.KnownBackend t ds b)
  => Dict (PrimBytes (Backend i t ds b))
inferPrimBytes :: Dict (PrimBytes (Backend i t ds b))
inferPrimBytes
    = (PrimBytes b :- PrimBytes (Backend i t ds b))
-> Dict (PrimBytes b) -> Dict (PrimBytes (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict PrimBytes b :- PrimBytes (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (PrimBytes b) -> Dict (PrimBytes (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (PrimBytes b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (PrimBytes (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- PrimBytes b)
-> Dict (b ~ BackendFamily t ds) -> Dict (PrimBytes b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (PrimBytes b))
-> (b ~ BackendFamily t ds) :- PrimBytes b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall t (ds :: [Nat]) b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
forall b (c :: * -> Constraint).
(KnownBackend t ds b, c (ScalarBase t), c FloatX2, c FloatX3,
 c FloatX4, c DoubleX2, c DoubleX3, c DoubleX4, c (ArrayBase t ds),
 b ~ BackendFamily t ds) =>
Dict (c b)
Impl.inferBackendInstance @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (PrimBytes (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (PrimBytes (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined

inferPrimArray
  :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
   . (PrimBytes t, Impl.KnownBackend t ds b)
  => Dict (PrimArray t (Backend i t ds b))
inferPrimArray :: Dict (PrimArray t (Backend i t ds b))
inferPrimArray
    = (PrimArray t b :- PrimArray t (Backend i t ds b))
-> Dict (PrimArray t b) -> Dict (PrimArray t (Backend i t ds b))
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict PrimArray t b :- PrimArray t (Backend i t ds b)
forall (c :: * -> Constraint) t (ds :: [Nat]) b i.
c b :- c (Backend i t ds b)
toBackend
    (Dict (PrimArray t b) -> Dict (PrimArray t (Backend i t ds b)))
-> (Dict (b ~ BackendFamily t ds) -> Dict (PrimArray t b))
-> Dict (b ~ BackendFamily t ds)
-> Dict (PrimArray t (Backend i t ds b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b ~ BackendFamily t ds) :- PrimArray t b)
-> Dict (b ~ BackendFamily t ds) -> Dict (PrimArray t b)
forall (a :: Constraint) (b :: Constraint).
(a :- b) -> Dict a -> Dict b
mapDict (((b ~ BackendFamily t ds) => Dict (PrimArray t b))
-> (b ~ BackendFamily t ds) :- PrimArray t b
forall (a :: Constraint) (b :: Constraint). (a => Dict b) -> a :- b
Sub (forall b.
(PrimBytes t, KnownBackend t ds b, b ~ BackendFamily t ds) =>
Dict (PrimArray t b)
forall t (ds :: [Nat]) b.
(PrimBytes t, KnownBackend t ds b, b ~ BackendFamily t ds) =>
Dict (PrimArray t b)
Impl.inferPrimArray @t @ds))
    (Dict (b ~ BackendFamily t ds)
 -> Dict (PrimArray t (Backend i t ds b)))
-> Dict (b ~ BackendFamily t ds)
-> Dict (PrimArray t (Backend i t ds b))
forall a b. (a -> b) -> a -> b
$ Backend Any t ds b -> Dict (DeriveContext (Backend Any t ds b))
forall t (ds :: [Nat]) b i.
Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext @t @ds @b Backend Any t ds b
forall a. HasCallStack => a
undefined


-- This is the rule that cannot be encoded in the type system, but enforced
-- as an invariant: Backend t ds b implies DeriveContext t ds b
inferDeriveContext :: forall (t :: Type) (ds :: [Nat]) (b :: Type) (i :: Type)
                    . Backend i t ds b
                   -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext :: Backend i t ds b -> Dict (DeriveContext (Backend i t ds b))
inferDeriveContext Backend i t ds b
_ = Dict (b ~ b) -> Dict (b ~ BackendFamily t ds)
forall a b. a -> b
unsafeCoerce (Dict (b ~ b)
forall (a :: Constraint). a => Dict a
Dict :: Dict (b ~ b))
{-# INLINE inferDeriveContext #-}

-- Backend is the newtype wrapper over b.
-- It has the same represenation and I expect it to have the same instance behavior.
toBackend :: forall c t ds b i . c b :- c (Backend i t ds b)
toBackend :: c b :- c (Backend i t ds b)
toBackend = (b -> Backend i t ds b) -> c b :- c (Backend i t ds b)
forall n o (t :: * -> Constraint).
Coercible n o =>
(o -> n) -> t o :- t n
unsafeDerive b -> Backend i t ds b
forall i t (ds :: [Nat]) backend. backend -> Backend i t ds backend
Backend
{-# INLINE toBackend #-}