Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scalar versus Functorial #114

Closed
tonyday567 opened this issue Jul 26, 2018 · 3 comments
Closed

Scalar versus Functorial #114

tonyday567 opened this issue Jul 26, 2018 · 3 comments

Comments

@tonyday567
Copy link
Owner

Turning my attention to ocramz/sparse-linear-algebra#60

Interpreted for numhask naming conventions, the library defines this:

class (Subtractive a, Multiplicative (Scalar a)) => VectorSpace a where
  type Scalar a :: *
  (.*) :: Scalar a -> a -> a

class VectorSpace a => InnerSpace a where
  (<.>) :: a -> a -> Scalar a

The current numhask approach is to "push" the Scalar (or Element) type to the headline, and eschew the Scalar type inside the class definition:

class (Multiplicative a) => MultiplicativeAction r a where
  (.*) :: r a -> a -> r a

class (Ring a, Divisive (r a), MultiplicativeAction r a) => Module r a

class (Module a) => Hilbert r a where
  (<.>) :: r a -> r a -> a

https://en.wikipedia.org/wiki/Vector_space

Conversion would be straight forward.

instance (MultiplicativeAction r a) => VectorSpace (r a) where
  type Scalar (r a) :: a
  (.*) = coerce (flip (.*))

instance (VectorSpace v) => MultiplicativeAction a (Scalar a) where
  (.*) = coerce (flip (.*))

My (outdated by now) experience with Scalar in subhask was that it caused a lot of constraint explosion for no good reason - plenty of Scalar s ~s etc. In sla, there is also:

class (Eq e , Fractional e, Floating e, Num (EltMag e), Ord (EltMag e)) => Elt e where
  type EltMag e :: *

which tends to be unnecessary in numhask.

Having said this, I'm wide open for potential solutions, from status quo, to having both, to going with Scalar etc etc.

@ocramz
Copy link
Collaborator

ocramz commented Jul 26, 2018

@tonyday567 very interesting, thank you for your insight! Yes I agree the Scalar type family really looks like poor design, I didn't come up with anything better at the time.

@tonyday567
Copy link
Owner Author

Not so fast at hitting the self-deprecation button! It's the boiler-plate solution for every other higher-kinded number library out there.

If you have like a Matrix 3 3 Int and you want to treat that as composed of 3 Vector 3 Ints, in other words, you want to be able to say m .* v, then you can say instance VectorSpace (Matrix 3 3 Int); type Scalar m = Vector 3 Int. The numhask way would be instance MultiplicativeAction (Vector 3) (Vector 3 Int). First way adds flexibility.

@LeanderK
Copy link
Collaborator

I agree. It's very inflexible because it enforces a hard design-constraint on your type and could lead to very convoluted types if you have a complicated scalar. Also, some types just may not fit the pattern.

I like your example of @tonyday567. What you want to construct is usually seen as a direct sum of vector-spaces (where we view the matrix as a sum of vectors). We ideally want to express both things, but I think for the later, the direct sum, the abstraction is too liberal. The type of the scalar and the type of the thing must not go out of sync (when doing matrix-multiplication etc.), which could lead to bugs and in general, seems like a very fragile solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants