Skip to content

jyp/gasp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gasp! Algebra Structures Prelude

This is another set of Haskell classes for algebraic structures. It may be used as an alternative prelude for numeric stuff.

Design notes

Scaling.

There is a tension between scalable types and multiplicatives.

Certain types are both vectors (scalable) and ring element (multiplicative). For instance:

  • Polynomials, Complex.

intances Scalable c (Poly x c) intances Multiplicative (Poly x c)

  • It’s nice if Multiplicative x implies Scalable x x

Overlappable Option (chosen)

Ring x implies Scalable x x

So if F b is a ring and has a module stucture, we might have:

Scalable (F a) (F a) Scalable a (F a) (1)

That’s 100% fine and GHC can see that.

Issue 1 (benign). When using a literal scalar, GHC can’t determine the scalar type to use. This means that type annotations are often needed This is mitigated by type applications. Exported named defaults may come soon to help as well.

Issue 2. We may want to generalise (1) to:

Scalable s a => Scalable s (F a) (2)

Now, this instance overlaps with Scalable (F a) (F a).

Indeed, Scalable (F a) (F a) can be solved via (2) if Scalable (F a) a is ever defined.

This should however never be defined, because F a is a strictly bigger type than a for every a. So it makes no sense have (F a) be a scalar for a for any a.

In sum, as long as the overlappable instances strictly decrease the size of types (in the 2nd argument position), we’re fine. Obviously, instances should additionally be coherent!

Scalar new type option (not chosen)

Scalable scalar vector | vector -> scalar

vector could determine scalar. This cannot be done without some sort of annotations. Consider:

vector = Vector (Polynomial x c)

The scalar could be c or Polynomial x c.

So this would require adding a newtype “Scalar” indicating which type would be the scalar:

Vector (Scalar (Polynomial x c))

Vector (Polynomial x (Scalar c))

For scalars, we lift Multiplicative instances to Scalable:

instance Scalable (Scalar x) (Scalar x) where Scalar x *^ Scalar y = Scalar (x*y)

Typically, generic code is unaffected. Or better, because we can always work with Scalable s a => Vector a or such.

But working with concrete types require conversions. Perhaps coercions can make this pleasant? https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Coerce.html

Functors Options

scale x = fmap (x*)

  • investigated in Algebra.Linear
  • This prevents using scaling for scalar types or for efficient representations (say unboxed arrays)

About

Another Haskell Prelude for Algebraic Classes and Structures

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published