haskell / haskell/time

More algebraic structure

Open
#280 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
135
Forks
83
PR merge metrics
No merged PRs in 30d

Description

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](https://math.ucr.edu/home/baez/torsors.html) to get the gist of torsors.
1. See also #281, although this and that can be done independently.
1. `Torsor` and especially `Group` are generally useful classes; it might be a bit odd to define them in the time library.
1. Should also do #277 with this.
1. 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 ...`
1. 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`.
1. This sort of thing has been attempted elsewhere:
- [torsor](https://hackage.haskell.org/package/torsor)
- [monoid-extras](https://hackage.haskell.org/package/monoid-extras)
- [lr-acts](https://hackage.haskell.org/package/lr-acts)
1. 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
1. 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
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.