From 62a14197f2239ce2f7405f15aec24b12d37cee55 Mon Sep 17 00:00:00 2001 From: Joris Date: Thu, 9 Feb 2023 12:05:40 +0100 Subject: [PATCH] Populate `README.md` for `simple-semigroupoids` package. --- simple-semigroupoids/README.md | 68 ++++++++++++++++++- .../simple-semigroupoids.cabal | 2 +- .../src/Data/Semigroupoid/Simple.hs | 4 +- 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/simple-semigroupoids/README.md b/simple-semigroupoids/README.md index 03bfd90..976107c 100644 --- a/simple-semigroupoids/README.md +++ b/simple-semigroupoids/README.md @@ -1 +1,67 @@ -# simple-semigroupoids \ No newline at end of file +# 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] +``` \ No newline at end of file diff --git a/simple-semigroupoids/simple-semigroupoids.cabal b/simple-semigroupoids/simple-semigroupoids.cabal index e0e36b4..164f9ab 100644 --- a/simple-semigroupoids/simple-semigroupoids.cabal +++ b/simple-semigroupoids/simple-semigroupoids.cabal @@ -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 diff --git a/simple-semigroupoids/src/Data/Semigroupoid/Simple.hs b/simple-semigroupoids/src/Data/Semigroupoid/Simple.hs index 1e5197d..c65ce40 100644 --- a/simple-semigroupoids/src/Data/Semigroupoid/Simple.hs +++ b/simple-semigroupoids/src/Data/Semigroupoid/Simple.hs @@ -23,7 +23,7 @@ infix 6 <>? -- -- The following laws are from -- , 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 @@ -53,7 +53,7 @@ pappendUnsafe l r = case l <>? r of -- -- The following laws are from -- , with @*@ representing --- 'poperatorM'. +-- 'pappendM'. -- -- /Inverse/ @Just ('pinv' x) ∗ Just x@ and @Just x ∗ Just ('pinv' x)@ are -- always defined.