neural-0.3.0.1: src/Data/FixedSize/Volume.hs
{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
Module : Data.FixedSize.Volume
Description : fixed-size volumes
Copyright : (c) Lars Brünjes, 2016
License : MIT
Maintainer : brunjlar@gmail.com
Stability : experimental
Portability : portable
This module defines fixed-size /volumes/ and some basic typeclass instances and operations for them.
A 'Volume' is a 'Matrix' with 'Vector' entries, i.e. a three-dimensional array.
-}
module Data.FixedSize.Volume
( Volume(..)
, toVolume
, slice
, fromMatrix
) where
import Data.MyPrelude
import Data.FixedSize.Class
import Data.FixedSize.Matrix
import Data.FixedSize.Vector
import GHC.TypeLits
-- | @'Volume' m n d a@ is the type of /volumes/ with @m@ rows, @n@ columns, depth @d@ and entries of type @a@.
--
newtype Volume (m :: Nat) (n :: Nat) (d :: Nat) a = Volume (Matrix m n (Vector d a))
deriving (Eq, Show, Functor, Foldable, Traversable, NFData)
-- | Converts a 'Matrix' of 'Vector's to the equivalent 'Volume'.
--
toVolume :: Matrix m n (Vector d a) -> Volume m n d a
toVolume = Volume
instance (KnownNat m, KnownNat n, KnownNat d) => Applicative (Volume m n d) where
pure x = Volume $ pure (pure x)
Volume fs <*> Volume xs = Volume $ (<*>) <$> fs <*> xs
instance (KnownNat m, KnownNat n, KnownNat d) => FixedSize (Volume m n d) where
type Index (Volume m n d) = (Int, Int, Int)
type Size (Volume m n d) = m * n * d
Volume m !? (i, j, k) = m !? (i, j) >>= (!? k)
generate f = Volume $ generate (\(i, j) -> generate (\k -> f (i, j, k)))
-- | @'slice' v i@ gives the matrix "at depth @i@" of volume @v@ (or 'Nothing' if @i@ is invalid).
--
-- >>> :set -XDataKinds
-- >>> slice (pure True :: Volume 2 2 3 Bool) 2
-- Just (Matrix [[True,True],[True,True]])
--
-- >>> slice (pure True :: Volume 2 2 3 Bool) 3
-- Nothing
--
slice :: KnownNat d => Volume m n d a -> Int -> Maybe (Matrix m n a)
slice (Volume m) i = sequenceA $ (!? i) <$> m
-- | Converts a 'Matrix' into a 'Volume' of depth one.
--
-- >>> fromMatrix (pure 0) :: Volume 2 2 1 Int
-- Volume (Matrix [[[0],[0]],[[0],[0]]])
--
fromMatrix :: Matrix m n a -> Volume m n 1 a
fromMatrix = Volume . fmap pure