Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion simple-semigroupoids/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
# simple-semigroupoids
# simple-semigroupoids

This package implements simple versions of type classes for groupoid-like types.
In addition, this package provides helpers for testing type class laws for
group-like and groupoid-like types.

## Groupoid-like types: semigroupoids and groupoids

A `Semigroupoid` is like a `Semigroup`, but the binary sum operator `(<>)` is
now a partial operation `(<>?)`. A `Groupoid` is a `Semigroupoid` with a unary
invert operation `pinv`. A `Groupoid` is similar to what a `Group` is to a
`Semigroup`.

```haskell
class Semigroupoid a where (<>?) :: a -> a -> Maybe a
class Semigroupoid a => Groupoid a where pinv :: a -> a
```

Instances of the `Semigroupoid` class should adhere to the *associativity law*.
Instances of the `Groupoid` class should adhere to the *inverse law* and the
*identity law*. An algebraic definition of semigroupoids/groupoids can be found
[here](https://en.wikipedia.org/wiki/Groupoid#Algebraic). The documentation in
the `Data.Semigroupoid.Simple` module restates these properties/laws in terms of
Haskell terms and types.

Semigroupoids are a more general definition of semigroups, and groupoids are a
more general definition of groups. This means that by definition, a semigroup is
also a semigroupoid, and a group is also a groupoid. The `Auto a` newtype in
`Data.Semigroupoids.Auto` automatically derives a `Semigroupoid` or `Groupoid`
instance for `Auto a` in case `a` is a `Semigroup` or `Group` respectively.

```haskell
newtype Auto a = Auto a
deriving newtype (Semigroup, Monoid, Group)

instance Semigroup (Auto a) => Semigroupoid (Auto a) where
x <>? y = Just $ x <> y

instance Group (Auto a) => Groupoid (Auto a) where
pinv = invert
```

## Helpers for testing type-class laws

The `Data.Semigroupoid.Simple.Laws` module provides helpers for creating `tasty`
`TestTree`s that test type class laws for group-like and groupoid-like types.
For example, `testSemigroupLaws` will test the associativity law for the
`Semigroup` type class, given some proxy of the type that is under test.

```haskell
testSemigroupLaws ::
( Semigroup a, Arbitrary a
, Eq a, Show a
)
=> Proxy a
-> TestTree
```

Using `testGroupWithProxy` makes testing type class laws as easy as providing a
proxy of the type under test, and a list of type class law test functions.

```haskell
testGroupWithProxy :: Typeable a => Proxy a -> [Proxy a -> TestTree] -> TestTree

tests :: TestTree
tests = testgroupWithProxy (Proxy @(Sum Int)) [testSemigroupLaws, testGroupLaws]
```
2 changes: 1 addition & 1 deletion simple-semigroupoids/simple-semigroupoids.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ author: Joris Dral
maintainer: operations@iohk.io
category: Control, Testing
build-type: Simple
tested-with: GHC == { 8.10.7, 9.2.5 }
tested-with: GHC == { 8.10.7, 9.2.5 }

library
default-language: Haskell2010
Expand Down
4 changes: 2 additions & 2 deletions simple-semigroupoids/src/Data/Semigroupoid/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ infix 6 <>?
--
-- The following laws are from
-- <https://en.wikipedia.org/wiki/Groupoid#Algebraic>, with @*@ representing
-- 'poperatorM'.
-- 'pappendM'.
--
-- /Associativity/ If @Just x ∗ Just y@ and @Just y ∗ Just z@ are defined, then
-- @(Just x ∗ Just y) ∗ Just z@ and @Just x ∗ (Just y ∗ Just z)@ are defined and
Expand Down Expand Up @@ -53,7 +53,7 @@ pappendUnsafe l r = case l <>? r of
--
-- The following laws are from
-- <https://en.wikipedia.org/wiki/Groupoid#Algebraic>, with @*@ representing
-- 'poperatorM'.
-- 'pappendM'.
--
-- /Inverse/ @Just ('pinv' x) ∗ Just x@ and @Just x ∗ Just ('pinv' x)@ are
-- always defined.
Expand Down