我定义了一个具有存在隐藏维度的矩阵类型,因此我可以形成任意大小的矩阵列表:
import qualified Data.Vector.Sized as VS
import Data.Vector.Sized (Vector)
-- | A matrix with existentially hidden dimensions.
data Mat :: * -> * where
Mat :: (Vector m :.: Vector n) a -> Mat a
但是,现在,我无法弄清楚如何以类型检查的方式定义矩阵向量乘法函数。 试试这个:
| Matrix-vector multiplication for existentially typed matrices.
(^*^)
:: (KnownNat m, KnownNat n, Num a)
=> Mat a -- ^ transform matrix
-> Vector n a -- ^ input vector
-> Vector m a
Mat (Comp1 mat) ^*^ v = VS.map (dot v) mat
dot :: (KnownNat n, Num a) => Vector n a -> Vector n a -> a
u `dot` v = VS.sum $ VS.zipWith (*) u v
结果:
• Couldn't match type ‘m1’ with ‘m’
‘m1’ is a rigid type variable bound by
a pattern with constructor:
Mat :: forall a (m :: Nat) (n :: Nat).
(:.:) (Vector m) (Vector n) a -> Mat a,
in an equation for ‘^*^’
at src/RL/MulES.hs:89:1-15
‘m’ is a rigid type variable bound by
the type signature for:
(^*^) :: forall (m :: Nat) (n :: Nat) a.
(KnownNat m, KnownNat n) =>
Mat a -> Vector n a -> Vector m a
at src/RL/MulES.hs:(84,1)-(88,15)
Expected type: Vector m a
Actual type: Vector m1 a
• In the expression: VS.map (dot v) mat
In an equation for ‘^*^’:
Mat (Comp1 mat) ^*^ v = VS.map (dot v) mat
• Relevant bindings include
mat :: Vector m1 (Vector n8 a) (bound at src/RL/MulES.hs:89:12)
(^*^) :: Mat a -> Vector n a -> Vector m a
(bound at src/RL/MulES.hs:89:17)
|
89 | Mat (Comp1 mat) ^*^ v = VS.map (dot v) mat
| ^^^^^^^^^^^^^^^^^^
答案 0 :(得分:2)
首先让我说一下,我发现这个想法非常可疑:如果你再用一个存在的包装器把它扔掉,为什么还要通过类型系统来修复尺寸呢?
由于您不知道该线性映射的域维度,因此您可以应用它的唯一向量是可以按需提供任何维度的向量。这很疯狂,但可以使用-XRank2Types
在Haskell中表达。此外,您还不知道codomain维度,因此结果必须再次存在。存在包装器必须包含KnownNat
约束,否则你根本无法对向量做任何事情。像
{-# LANGUAGE GADTs, Rank2Types, UnicodeSyntax #-}
-- | This is really just a pretentious replacement for Data.Vector.Vector
data Array :: * -> * where
Array :: KnownNat n => Vector n a -> Mat a
data Mat :: * -> * where
Mat :: (KnownNat n, KnownNat m) => (Vector m :.: Vector n) a -> Mat a
lapply :: Num a => Mat a -> (∀ n . KnownNat n => Vector n a) -> Array a
lapply (Mat m) v = Array $ VS.map (dot v) mat
这对任何事都有用吗?不确定。你真的可以创建这样一个长度不可知的向量,如果你真正想要表达的是一个连续函数,它是在统一网格上进行PCM采样的(Matlab人们整天都在使用它,而不是有适当的功能类型...)。采样将自动调整到矩阵要求的任何分辨率。
但是,在运行时这只意味着你的输入“vector”实际上是一个采用resolution-argument的函数。整个类型级数foo在这里买不到多少。
IMO,当你发现自己处理这种“可变长度向量”时,它通常表明你真正在无限维向量空间中工作,就像通常一样这样的功能空间。 (最广泛使用的这样的空间是L2 Hilbert space。)这不能用任何基于数组的方法表达,但是如果你放弃维度/元素,它就可以表达分解,而是使用向量空间作为类型类。 Conal Elliott's package因为这已经存在很长时间了;它可能看起来有点过时但实际上仍然非常实用。我花了一些力气在它上面a proper category of linear maps,但是它还没有达到使它完全可用于无限维空间的程度。