dunai-0.10.0: src/Data/MonadicStreamFunction/Instances/VectorSpace.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- |
-- Copyright : (c) Ivan Perez and Manuel Baerenz, 2016
-- License : BSD3
-- Maintainer : ivan.perez@keera.co.uk
--
-- 'VectorSpace' instances for 'MSF's that produce vector spaces. This allows
-- you to use vector operators with 'MSF's that output vectors, for example,
-- you can write:
--
-- @
-- msf1 :: MSF Input (Double, Double) -- defined however you want
-- msf2 :: MSF Input (Double, Double) -- defined however you want
-- msf3 :: MSF Input (Double, Double)
-- msf3 = msf1 ^+^ msf2
-- @
--
-- instead of
--
-- @
-- msf3 = (msf1 &&& msf2) >>> arr (uncurry (^+^))
-- @
--
--
-- Instances are provided for the type class 'VectorSpace'.
-- Note: This module uses undecidable instances, because GHC does not know
-- enough to assert that it will be able to determine the type of 's' from the
-- type of 'v', because 'v' only appears under 'MSF' in the instance head and
-- it cannot determine what 'MSF' will do to 'v' and whether the type can be
-- resolved.
module Data.MonadicStreamFunction.Instances.VectorSpace where
-- External imports
import Control.Arrow ((>>^))
import Data.VectorSpace (VectorSpace (..))
-- Internal imports
import Control.Arrow.Util (constantly, elementwise2)
import Data.MonadicStreamFunction.Core (MSF)
-- | Vector-space instance for 'MSF's.
instance (Monad m, Eq s, Num s, VectorSpace v s, Floating (MSF m a s))
=> VectorSpace (MSF m a v) (MSF m a s)
where
zeroVector = constantly zeroVector
(*^) = elementwise2 (*^)
(^/) = elementwise2 (^/)
(^+^) = elementwise2 (^+^)
(^-^) = elementwise2 (^-^)
negateVector = (>>^ negateVector)
dot = elementwise2 dot
normalize v = elementwise2 f v (norm v)
where
f v' nv'
| nv' /= 0 = v' ^/ nv'
| otherwise = error "normalize: zero vector"