我想在netwire中使用线性代数库。由于netwire的类型是Applicative
的实例,因此它为其类型提供Num
和Fractional
个实例,以自动liftA2
相应的函数。这很好,因为你可以做一些事情,比如增加时变值,而不需要额外的努力。
我一直在使用线性,但它的函数被定义为非*
类型的多态,即矩阵乘积:
(!*!) :: (Functor m, Foldable t, Additive t, Additive n, Num a)
=> m (t a) -> t (n a) -> m (n a)
这意味着,如果我没有太多错误,我无法为Additive
和公司定义实例,因为实例没有合理的形式。虽然我可以写
instance Num b => Num (Wire s e m a b) where ...
没有办法写
instance Additive n => Additive (Wire s e m a (n x)) where ...
因为(Wire s e m a (n x))
的类型错误(*
而不是* -> *
)。我见过的其他图书馆根本就没有多态性。
我想知道的是,哪种线性代数库是多态的*
?
我看过Vec,看起来好多了。它的矩阵乘法有
类型(Map v v' m1 m3, Map v a b v', Transpose m2 b, Fold v a, Num v, Num a)
=> m1 -> m2 -> m3
这就是我想要的。还有其他这样的图书馆吗?
答案 0 :(得分:3)
有vector-space,它确实在许多方面比通过其标量参数化的库更优雅(VectorSpace
将该字段替换为关联类型同义词。)
我喜欢它的部分原因是它完全不是基于免费向量空间linear,这意味着基于Foldables
的签名不会任何意义上的首要任务。 (实际上,它根本没有讨论矩阵,只讨论linear mappings,这只是the morphisms of the category of vector spaces)
instance (AdditiveGroup a) => AdditiveGroup (Wire a) where
...
instance (VectorSpace v) => VectorSpace (Wire v) where
type Scalar (Wire v) = Scalar v -- Or perhaps `Wire (Scalar v)`
...
答案 1 :(得分:1)
我做了一些其他图书馆的调查,这是我发现的:
* -> *
,GPL许可dot
之类的内容无法解除* -> *
个班级Matrix (Wire s e m a Double)
是一个携带基质的电线);没有OpenGL接口除了Vec,矢量空间和住宿加早餐外,它们除外。不稳定的类型消除了床和早餐(不幸的是,因为它不是很好)。最后,Vec最终在矢量空间上获得了一点点,因为它似乎是为图形而不是抽象代数研究而设计的。而且因为我似乎无法弄清楚如何使用线性地图进行透视变换。
我将不得不编写一个OpenGL接口(因为它已经Storable
,所以不应该太糟糕)。唯一的缺点是我无法想到一个合理的类型类依赖于维度的参数/辅助函数的结果(即rotationX :: Floating a => a -> Mat44 a
)。这是我用Vec输掉的向量空间的优势之一。
更新:Vec不起作用。这些类不仅适用于结果类型,它们也适用于放入向量的类型。例如,Fold
类。
最终更新:我最终放弃了这个想法并为Wire
创建了单独的函数。