Skip to content

More algebraic structure #280

@AshleyYakeley

Description

@AshleyYakeley

Not sure exactly how best to do this, but something like:

instance Semigroup DiffTime
instance Monoid DiffTime
instance Semigroup NominalDiffTime
instance Monoid NominalDiffTime

class Monoid a => Group a where
    negateG :: a -> a
    (~~) :: a -> a -> a
    scaleG :: Int -> a -> a

instance Num a => Group (Sum a)  -- but what about Natural?
instance Group DiffTime
instance Group NominalDiffTime

class Group (TorsorGroup a) => Torsor a where
    type TorsorGroup a :: *
    addT :: TorsorGroup a -> a -> a
    diffT :: a -> a -> TorsorGroup a

instance Torsor Day where
    type Torsor Day = Sum Integer
    ...

instance Torsor UTCTime where
    type Torsor UTCTime = NominalDiffTime
    ...

-- etc. for other time types

Notes

Using this as a scratch-pad for ideas, editing often.

  1. See Baez to get the gist of torsors.
  2. See also type NominalDiffTime = DiffTime #281, although this and that can be done independently.
  3. Torsor and especially Group are generally useful classes; it might be a bit odd to define them in the time library.
  4. Should also do Functions to truncate time types #277 with this.
  5. A stricter definition of Group would be class (Monoid a, Torsor a, TorsorGroup a ~ a) => Group a, not sure if that's too annoying.
    • Alternatively can do instance {-# OVERLAPPABLE #-} Group a => Torsor a where ...
  6. There's a bit of tension between the concepts "monoid" and "additive monoid" (likewise "group", etc.), and we use the Sum type to bridge the gap. For example there isn't an instance Monoid Integer (using addition) because there can be other monoids on Integer.
  7. This sort of thing has been attempted elsewhere:
  8. A nice way of looking at some of the classes is to consider the domain of the scaling function :: i -> a -> a:
    • i is the positive integers: semigroup
    • i is the non-negative integers: monoid
    • i is the integers: group
    • i is the rationals or reals: one-dimension vector space over rationals or reals
  9. There probably isn't a need to add a "one-dimension vector space" class (what members would it have?) even though UTCTime would morally be an instance.

Expanding on point 5, it is possible to collapse Group into Torsor:

class Group (TorsorGroup a) => Torsor a where
    type TorsorGroup a :: *
    addT :: TorsorGroup a -> a -> a
    (~~) :: a -> a -> TorsorGroup a

type Group a = (Monoid a, Torsor a, TorsorGroup a ~ a)

negateG :: Group a => a -> a
negateG x = mempty ~~ x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions