[Haskell-cafe] vector-space and standard API for vectors

wren ng thornton wren at freegeek.org
Sat Oct 23 19:38:54 EDT 2010

On 10/23/10 4:53 PM, Alexey Khudyakov wrote:
> On 23.10.2010 05:11, wren ng thornton wrote:
>> I'd rather see,
>> class Additive v where -- or AdditiveMonoid, if preferred
>> zeroV :: v
>> (^+^) :: v -> v -> v
>> class Additive v => AdditiveGroup v where
>> negateV :: v -> v
> Seems good for me. One more instance declaration to write and no changes
> in usage.
> However when written this way it becomes obvious that
> `zeroV' == `mempty' and ^+^ = mappend. Is Additive really needed then?

It depends on the usage, since we don't have a nice way of having 
multiple Monoid instances in scope with different identifiers for their 
respective mzero/mappend. For example, in Edward Kmett's monoids[1] 
library he reuses Monoid for additive monoids and adds a new 
Multiplicative class for multiplicative monoids; that way you can use 
operators for a semiring without needing newtype wrappers everywhere in 
order to distinguish the two structures on the same type.

When dealing with modules and vector spaces we have three or four 
different monoids in play: the additive and multiplicative monoids of 
the underlying semiring/ring/field, and the additive and multiplicative 
monoids of the module/vectorspace. Lacking the aforementioned feature, 
that means there are good reasons to have duplicate classes (i.e., 
they're all monoids) so long as they are documented as capturing 
different notions (e.g., distinguishing "scalar" and "vectorial" uses).

I don't care much about the name of the class, I'd just like support for 
monoids, semirings,... when they lack a group, ring,... structure.

[1] http://hackage.haskell.org/package/monoids

>> type family Scalar :: * -> *
>> class Additive v => LeftModule v where
>> (*^) :: Scalar v -> v -> v
>> class Additive v => RightModule v where
>> (^*) :: v -> Scalar v -> v
> Could you give some example of data type for which (*^) ≠ flip (^*)?
> I couldn't imagine one.

Choose any underlying semiring/ring/field with non-commutative 
multiplication. For a simple one, consider collections of paths over a 
graph. Addition is choice, so union in the collection. Multiplication is 
concatenation, mapping over the collection. While xs+ys == ys+xs because 
union is commutative, xs*ys /= ys*xs because (*ys) adds ys to the end of 
the paths whereas (ys*) adds ys to the beginning of the path.

As Daniel Fischer mentions, quaternions are another common example.

Live well,

More information about the Haskell-Cafe mailing list