Reputation: 13160
I want to use a linear algebra library with netwire. Because netwire's types are instances of Applicative
, it provides Num
and Fractional
instances for its types that automagically liftA2
the appropriate function. This is nice because you can do things like multiply time-varying values without any extra effort.
I've been using linear, but its functions are defined to be polymorphic over a non-*
kind, ie the matrix product:
(!*!) :: (Functor m, Foldable t, Additive t, Additive n, Num a)
=> m (t a) -> t (n a) -> m (n a)
This means, if I am not much mistaken, that I can't define instances for Additive
and company, because there is no sane form for the instance to take. While I can write
instance Num b => Num (Wire s e m a b) where ...
there is no way to write
instance Additive n => Additive (Wire s e m a (n x)) where ...
because (Wire s e m a (n x))
has the wrong kind (*
as opposed to * -> *
). Other libraries I've seen aren't polymorphic at all.
What I want to know is, which linear algebra libraries are polymorphic over kind *
?
I've looked at Vec, which seems better. Its matrix multiply has type
(Map v v' m1 m3, Map v a b v', Transpose m2 b, Fold v a, Num v, Num a)
=> m1 -> m2 -> m3
which is what I want. Are there other libraries like this?
Upvotes: 4
Views: 326
Reputation: 13160
I did a survey of some other libraries, and here's what I found:
* -> *
, GPL licenseddot
can't be lifted* -> *
classesMatrix (Wire s e m a Double)
is a wire carrying matricies); no OpenGL interfaceThis eliminates all but Vec, vector-space, and bed-and-breakfast. The wonky types eliminate bed-and-breakfast (unfortunately, because it's otherwise nice). In the end Vec ends up winning just a little over vector-space because it seems to be designed for graphics rather than abstract algebra study. And because I can't seem to figure out how to make a perspective transformation with linear maps.
I'll have to write an OpenGL interface (which shouldn't be too bad since it's already Storable
). The only downside is that I can't think of a sensible typeclass for dimension-dependent arguments/results of auxiliary functions (ie rotationX :: Floating a => a -> Mat44 a
). This is one of the strengths of vector-space I lose with Vec.
Update: Vec will not work. The classes aren't just for result types, they are on types that get put into the vector as well. For instance, the Fold
class.
Final update: I ended up giving up on this idea and creating separate functions for Wire
s.
Upvotes: 1
Reputation: 120711
There's vector-space, which is indeed in many ways more elegant than the libraries that are parameterised over their scalars (VectorSpace
has that field instead as an associated type synonym).
Part of what I like about it is that it's totally not based on free vector spaces as linear is, which means a signature based on Foldables
wouldn't make any sense in the first place. (Indeed, it doesn't talk about matrices at all, only about linear mappings, which are simply 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)`
...
Upvotes: 3