Question

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?

Was it helpful?

Solution

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)`
  ...

OTHER TIPS

I did a survey of some other libraries, and here's what I found:

  • hmatrix - actively maintained; classes of kind * -> *, GPL licensed
  • vect - OpenGL bindings; not actively maintained; uses hardwired scalar types so things like dot can't be lifted
  • Vec - sort of actively maintained; not overloaded correctly (see below); useful auxiliary functions; no OpenGL bindings
  • linear - actively maintained; supported by GLUtil and vinyl-gl; * -> * classes
  • vector-space - sort of actively maintained; overloaded correctly; OpenGL bindings, but for vectors only; after an hour I still can't figure out how to use it, especially the linear mappings
  • Tensor - built into OpenGL; no math functions
  • bed-and-breakfast - actively maintained; uses unboxed arrays; uses type families on value type, so it could be overloaded but it would look weird (ie Matrix (Wire s e m a Double) is a wire carrying matricies); no OpenGL interface

This 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 Wires.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top