partial-semigroup-0.0.0.1: A partial binary associative operator

Safe HaskellNone
LanguageHaskell2010

Data.PartialSemigroup

Contents

Synopsis

Partial semigroup

class PartialSemigroup a where Source #

A partial semigroup is like a Semigroup, but with an operator returning Maybe a rather than a.

For comparison:

(<>)        :: Semigroup a        => a -> a -> a
appendMaybe :: PartialSemigroup a => a -> a -> Maybe a

The associative law for partial semigroups

For all x, y, z such that appendMaybe x y = Just xy and appendMaybe y z = Just yx, appendMaybe x yz = appendMaybe xy z.

Minimal complete definition

appendMaybe

Methods

appendMaybe :: a -> a -> Maybe a Source #

Instances

PartialSemigroup () Source # 

Methods

appendMaybe :: () -> () -> Maybe () Source #

PartialSemigroup [a] Source # 

Methods

appendMaybe :: [a] -> [a] -> Maybe [a] Source #

PartialSemigroup a => PartialSemigroup (Identity a) Source # 
PartialSemigroup a => PartialSemigroup (ZipList a) Source #

partialZip

Methods

appendMaybe :: ZipList a -> ZipList a -> Maybe (ZipList a) Source #

Num a => PartialSemigroup (Sum a) Source # 

Methods

appendMaybe :: Sum a -> Sum a -> Maybe (Sum a) Source #

Num a => PartialSemigroup (Product a) Source # 

Methods

appendMaybe :: Product a -> Product a -> Maybe (Product a) Source #

Semigroup a => PartialSemigroup (Total a) Source # 

Methods

appendMaybe :: Total a -> Total a -> Maybe (Total a) Source #

(PartialSemigroup a, PartialSemigroup b) => PartialSemigroup (Either a b) Source # 

Methods

appendMaybe :: Either a b -> Either a b -> Maybe (Either a b) Source #

(PartialSemigroup a, PartialSemigroup b) => PartialSemigroup (a, b) Source # 

Methods

appendMaybe :: (a, b) -> (a, b) -> Maybe (a, b) Source #

PartialSemigroup b => PartialSemigroup (AppendRight a b) Source # 
PartialSemigroup a => PartialSemigroup (AppendLeft a b) Source # 

Methods

appendMaybe :: AppendLeft a b -> AppendLeft a b -> Maybe (AppendLeft a b) Source #

(PartialSemigroup a, PartialSemigroup b, PartialSemigroup c) => PartialSemigroup (a, b, c) Source # 

Methods

appendMaybe :: (a, b, c) -> (a, b, c) -> Maybe (a, b, c) Source #

Either

The exemplary nontrivial PartialSemigroup is Either, for which the append operator produces a Just result only if both arguments are Left or both arguments are Right.

>>> appendMaybe (Left "ab") (Left "cd")
Just (Left "abcd")
>>> appendMaybe (Left "ab") (Right [1,2])
Nothing

newtype AppendLeft a b Source #

A wrapper for Either where the PartialSemigroup operator is defined only over Left values.

Examples

Two Lefts make a Just.

>>> appendMaybe (AppendLeft (Left "ab")) (AppendLeft (Left "cd"))
Just (AppendLeft {unAppendLeft = Left "abcd"})

Anything else produces Nothing

>>> appendMaybe (AppendLeft (Right "ab")) (AppendLeft (Right "cd"))
Nothing

groupAndConcat combines consecutive Left values, leaving the Right values unmodified.

>>> xs = [Left "a", Left "b", Right "c", Right "d", Left "e", Left "f"]
>>> fmap unAppendLeft . groupAndConcat . fmap AppendLeft $ xs
[Left "ab",Right "c",Right "d",Left "ef"]

Constructors

AppendLeft 

Fields

Instances

(Eq a, Eq b) => Eq (AppendLeft a b) Source # 

Methods

(==) :: AppendLeft a b -> AppendLeft a b -> Bool #

(/=) :: AppendLeft a b -> AppendLeft a b -> Bool #

(Ord a, Ord b) => Ord (AppendLeft a b) Source # 

Methods

compare :: AppendLeft a b -> AppendLeft a b -> Ordering #

(<) :: AppendLeft a b -> AppendLeft a b -> Bool #

(<=) :: AppendLeft a b -> AppendLeft a b -> Bool #

(>) :: AppendLeft a b -> AppendLeft a b -> Bool #

(>=) :: AppendLeft a b -> AppendLeft a b -> Bool #

max :: AppendLeft a b -> AppendLeft a b -> AppendLeft a b #

min :: AppendLeft a b -> AppendLeft a b -> AppendLeft a b #

(Read a, Read b) => Read (AppendLeft a b) Source # 
(Show a, Show b) => Show (AppendLeft a b) Source # 

Methods

showsPrec :: Int -> AppendLeft a b -> ShowS #

show :: AppendLeft a b -> String #

showList :: [AppendLeft a b] -> ShowS #

PartialSemigroup a => PartialSemigroup (AppendLeft a b) Source # 

Methods

appendMaybe :: AppendLeft a b -> AppendLeft a b -> Maybe (AppendLeft a b) Source #

newtype AppendRight a b Source #

A wrapper for Either where the PartialSemigroup operator is defined only over Right values.

Examples

Two Rights make a Just.

>>> appendMaybe (AppendRight (Right "ab")) (AppendRight (Right "cd"))
Just (AppendRight {unAppendRight = Right "abcd"})

Anything else produces Nothing

>>> appendMaybe (AppendRight (Left "ab")) (AppendRight (Left "cd"))
Nothing

groupAndConcat combines consecutive Right values, leaving the Left values unmodified.

>>> xs = [Left "a", Left "b", Right "c", Right "d", Left "e", Left "f"]
>>> fmap unAppendRight . groupAndConcat . fmap AppendRight $ xs
[Left "a",Left "b",Right "cd",Left "e",Left "f"]

Constructors

AppendRight 

Fields

Instances

(Eq a, Eq b) => Eq (AppendRight a b) Source # 

Methods

(==) :: AppendRight a b -> AppendRight a b -> Bool #

(/=) :: AppendRight a b -> AppendRight a b -> Bool #

(Ord a, Ord b) => Ord (AppendRight a b) Source # 

Methods

compare :: AppendRight a b -> AppendRight a b -> Ordering #

(<) :: AppendRight a b -> AppendRight a b -> Bool #

(<=) :: AppendRight a b -> AppendRight a b -> Bool #

(>) :: AppendRight a b -> AppendRight a b -> Bool #

(>=) :: AppendRight a b -> AppendRight a b -> Bool #

max :: AppendRight a b -> AppendRight a b -> AppendRight a b #

min :: AppendRight a b -> AppendRight a b -> AppendRight a b #

(Read a, Read b) => Read (AppendRight a b) Source # 
(Show a, Show b) => Show (AppendRight a b) Source # 

Methods

showsPrec :: Int -> AppendRight a b -> ShowS #

show :: AppendRight a b -> String #

showList :: [AppendRight a b] -> ShowS #

PartialSemigroup b => PartialSemigroup (AppendRight a b) Source # 

Tuples

A tuple forms a partial semigroups when all of its constituent parts have partial semigroups. The append operator returns a Just value when all of the fields' append operators must return Just values.

>>> x = (Left "ab", Right "hi")
>>> y = (Left "cd", Right "jk")
>>> appendMaybe x y
Just (Left "abcd",Right "hijk")
>>> x = (Left "ab", Right "hi")
>>> y = (Left "cd", Left "jk")
>>> appendMaybe x y
Nothing

Concatenation

groupAndConcat :: forall a. PartialSemigroup a => [a] -> [a] Source #

Apply a semigroup operation to any pairs of consecutive list elements where the semigroup operation is defined over them.

Examples

For Either, groupAndConcat combines contiguous sublists of Left and contiguous sublists of Right.

>>> xs = [Left "a", Right "b", Right "c", Left "d", Left "e", Left "f"]
>>> groupAndConcat xs
[Left "a",Right "bc",Left "def"]

partialConcat :: forall a. PartialSemigroup a => [a] -> Maybe a Source #

If xs is nonempty and the partial semigroup operator is defined for all pairs of values in xs, then partialConcat xs produces a Just result with the combination of all the values. Otherwise, returns Nothing.

Examples

When all values can combine, we get a Just of their combination.

>>> partialConcat [Left "a", Left "b", Left "c"]
Just (Left "abc")

When some values cannot be combined, we get Nothing.

>>> partialConcat [Left "a", Left "b", Right "c"]
Nothing

When the list is empty, we get Nothing.

>>> partialConcat []
Nothing

partialConcat1 :: forall a. PartialSemigroup a => NonEmpty a -> Maybe a Source #

Like partialConcat, but for non-empty lists.

Examples

When all values can combine, we get a Just of their combination.

>>> partialConcat1 (Left "a" :| [Left "b", Left "c"])
Just (Left "abc")

When some values cannot be combined, we get Nothing.

>>> partialConcat1 (Left "a" :| [Left "b", Right "c"])
Nothing

Zipping

partialZip :: forall a. PartialSemigroup a => [a] -> [a] -> Maybe [a] Source #

Examples

If lists are the same length and each pair of elements successfully, then we get a Just result.

>>> xs = [Left "a", Left "b", Right "c"]
>>> ys = [Left "1", Left "2", Right "3"]
>>> partialZip xs ys
Just [Left "a1",Left "b2",Right "c3"]

If the pairs do not all combine, then we get Nothing.

>>> xs = [Left "a", Left "b", Right "c"]
>>> ys = [Left "1", Right "2", Right "3"]
>>> partialZip xs ys
Nothing

If the lists have different lengths, then we get Nothing.

>>> xs = [Left "a", Left "b", Right "c"]
>>> ys = [Left "1", Left "2"]
>>> partialZip xs ys
Nothing

partialZip1 :: forall a. PartialSemigroup a => NonEmpty a -> NonEmpty a -> Maybe (NonEmpty a) Source #

Like partialZip, but for non-empty lists.

Examples

If lists are the same length and each pair of elements successfully, then we get a Just result.

>>> xs = Left "a" :| [Left "b", Right "c"]
>>> ys = Left "1" :| [Left "2", Right "3"]
>>> partialZip1 xs ys
Just (Left "a1" :| [Left "b2",Right "c3"])

If the pairs do not all combine, then we get Nothing.

>>> xs = Left "a" :| [Left "b", Right "c"]
>>> ys = Left "1" :| [Right "2", Right "3"]
>>> partialZip1 xs ys
Nothing

If the lists have different lengths, then we get Nothing.

>>> xs = Left "a" :| [Left "b", Right "c"]
>>> ys = Left "1" :| [Left "2"]
>>> partialZip1 xs ys
Nothing

Total semigroups

Every type with a Semigroup can be given a trivial PartialSemigroup instance defined as:

appendMaybe x y = Just (x <> y)

Additionally, any type with a Semigroup can be treated as a PartialSemigroup by lifting it into Total.

newtype Total a Source #

A wrapper to turn any value with a Semigroup instance into a value with a PartialSemigroup instance whose appendMaybe operator always returns Just.

Examples

>>> appendMaybe (Total "ab") (Total "cd")
Just (Total {unTotal = "abcd"})
>>> f = getProduct . unTotal
>>> g = Total . Product
>>> fmap f . partialConcat . fmap g $ [1..4]
Just 24

Constructors

Total 

Fields

Instances

Eq a => Eq (Total a) Source # 

Methods

(==) :: Total a -> Total a -> Bool #

(/=) :: Total a -> Total a -> Bool #

Ord a => Ord (Total a) Source # 

Methods

compare :: Total a -> Total a -> Ordering #

(<) :: Total a -> Total a -> Bool #

(<=) :: Total a -> Total a -> Bool #

(>) :: Total a -> Total a -> Bool #

(>=) :: Total a -> Total a -> Bool #

max :: Total a -> Total a -> Total a #

min :: Total a -> Total a -> Total a #

Read a => Read (Total a) Source # 
Show a => Show (Total a) Source # 

Methods

showsPrec :: Int -> Total a -> ShowS #

show :: Total a -> String #

showList :: [Total a] -> ShowS #

Semigroup a => PartialSemigroup (Total a) Source # 

Methods

appendMaybe :: Total a -> Total a -> Maybe (Total a) Source #

Error-propagating maybe

newtype Partial a Source #

A wrapper for Maybe with an error-propagating Semigroup.

Constructors

Partial 

Fields

Instances

Eq a => Eq (Partial a) Source # 

Methods

(==) :: Partial a -> Partial a -> Bool #

(/=) :: Partial a -> Partial a -> Bool #

Ord a => Ord (Partial a) Source # 

Methods

compare :: Partial a -> Partial a -> Ordering #

(<) :: Partial a -> Partial a -> Bool #

(<=) :: Partial a -> Partial a -> Bool #

(>) :: Partial a -> Partial a -> Bool #

(>=) :: Partial a -> Partial a -> Bool #

max :: Partial a -> Partial a -> Partial a #

min :: Partial a -> Partial a -> Partial a #

Read a => Read (Partial a) Source # 
Show a => Show (Partial a) Source # 

Methods

showsPrec :: Int -> Partial a -> ShowS #

show :: Partial a -> String #

showList :: [Partial a] -> ShowS #

PartialSemigroup a => Semigroup (Partial a) Source # 

Methods

(<>) :: Partial a -> Partial a -> Partial a #

sconcat :: NonEmpty (Partial a) -> Partial a #

stimes :: Integral b => b -> Partial a -> Partial a #

Monoid a => Monoid (Partial a) Source # 

Methods

mempty :: Partial a #

mappend :: Partial a -> Partial a -> Partial a #

mconcat :: [Partial a] -> Partial a #