fei-base-1.0.0: c-apis/MXNet/Base/Tensor.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilyDependencies #-}
module MXNet.Base.Tensor where
import Data.Bifunctor (bimap)
import Data.Kind (Constraint)
import RIO
import RIO.List (unzip)
import {-# SOURCE #-} MXNet.Base.NDArray
import MXNet.Base.Raw.Common
import MXNet.Base.Raw.NDArray
import MXNet.Base.Raw.Symbol
import MXNet.Base.Spec.Operator (ArgsHMap)
import MXNet.Base.Symbol
import MXNet.Base.Types
-- TensorApply is injective
type family TensorApply t = c | c -> t where
TensorApply NDArrayHandle = Maybe [NDArrayHandle] -> IO [NDArrayHandle]
TensorApply (NDArray a) = Maybe [NDArray a] -> IO [NDArray a]
TensorApply SymbolHandle = Text -> IO SymbolHandle
type family TensorMonad t :: * -> *
type instance TensorMonad (NDArray a) = IO
type instance TensorMonad NDArrayHandle = IO
type TensorM t = TensorMonad t t
class TensorOp ti to where
apply :: HasCallStack => Text -> [(Text, Text)] -> Either [(Text, ti)] [ti] -> TensorApply to
class TensorOp ti to => PrimTensorOp ti to where
prim :: HasCallStack => (ArgsHMap s ti a -> TensorApply to) -> ArgsHMap s ti a -> TensorM to
instance TensorOp NDArrayHandle NDArrayHandle where
apply opname scalars tensors outputs = do
let tensors' = case tensors of
Left kwargs -> snd $ unzip kwargs
Right args -> args
op <- nnGetOpHandle opname
mxImperativeInvoke (fromOpHandle op) tensors' scalars outputs
instance (DType a, DType b) => TensorOp (NDArray a) (NDArray b) where
apply opname scalars tensors outputs = do
let tensors' = bimap (map (second unNDArray)) (map unNDArray) tensors
outputs' = fmap (map unNDArray) outputs :: Maybe [NDArrayHandle]
ret <- apply opname scalars tensors' outputs' :: IO [NDArrayHandle]
return $ map NDArray ret
instance TensorOp SymbolHandle SymbolHandle where
apply opname scalars tensors name = do
let (scalarkeys, scalarvals) = unzip scalars
(tensorkeys, tensorvals) = case tensors of
Left kwargs -> first Just $ unzip kwargs
Right args -> (Nothing, args)
op <- nnGetOpHandle opname
sym <- mxSymbolCreateAtomicSymbol (fromOpHandle op)
scalarkeys
scalarvals
mxSymbolCompose sym name tensorkeys tensorvals
return sym
instance PrimTensorOp NDArrayHandle NDArrayHandle where
prim op args = op args Nothing >>= \[x] -> return x
instance (DType a, DType b) => PrimTensorOp (NDArray a) (NDArray b) where
prim op args = op args Nothing >>= \[x] -> return x