Safe Haskell | None |
---|---|
Language | Haskell2010 |
- class PartialSemigroup a where
- newtype AppendLeft a b = AppendLeft {
- unAppendLeft :: Either a b
- newtype AppendRight a b = AppendRight {
- unAppendRight :: Either a b
- groupAndConcat :: forall a. PartialSemigroup a => [a] -> [a]
- partialConcat :: forall a. PartialSemigroup a => [a] -> Maybe a
- partialConcat1 :: forall a. PartialSemigroup a => NonEmpty a -> Maybe a
- partialZip :: forall a. PartialSemigroup a => [a] -> [a] -> Maybe [a]
- partialZip1 :: forall a. PartialSemigroup a => NonEmpty a -> NonEmpty a -> Maybe (NonEmpty a)
- newtype Total a = Total {
- unTotal :: a
- newtype Partial a = Partial {}
Partial semigroup
class PartialSemigroup a where Source #
A partial semigroup is like a Semigroup
, but with an operator returning
rather than Maybe
aa
.
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
.
appendMaybe :: a -> a -> Maybe a Source #
PartialSemigroup () Source # | |
PartialSemigroup [a] Source # | |
PartialSemigroup a => PartialSemigroup (Identity a) Source # | |
PartialSemigroup a => PartialSemigroup (ZipList a) Source # | |
Num a => PartialSemigroup (Sum a) Source # | |
Num a => PartialSemigroup (Product a) Source # | |
Semigroup a => PartialSemigroup (Total a) Source # | |
(PartialSemigroup a, PartialSemigroup b) => PartialSemigroup (Either a b) Source # | |
(PartialSemigroup a, PartialSemigroup b) => PartialSemigroup (a, b) Source # | |
PartialSemigroup b => PartialSemigroup (AppendRight a b) Source # | |
PartialSemigroup a => PartialSemigroup (AppendLeft a b) Source # | |
(PartialSemigroup a, PartialSemigroup b, PartialSemigroup c) => PartialSemigroup (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
>>>
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"]
AppendLeft | |
|
(Eq a, Eq b) => Eq (AppendLeft a b) Source # | |
(Ord a, Ord b) => Ord (AppendLeft a b) Source # | |
(Read a, Read b) => Read (AppendLeft a b) Source # | |
(Show a, Show b) => Show (AppendLeft a b) Source # | |
PartialSemigroup a => PartialSemigroup (AppendLeft a b) Source # | |
newtype AppendRight a b Source #
A wrapper for Either
where the PartialSemigroup
operator is defined
only over Right
values.
Examples
>>>
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"]
AppendRight | |
|
(Eq a, Eq b) => Eq (AppendRight a b) Source # | |
(Ord a, Ord b) => Ord (AppendRight a b) Source # | |
(Read a, Read b) => Read (AppendRight a b) Source # | |
(Show a, Show b) => Show (AppendRight a b) Source # | |
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
produces a partialConcat
xsJust
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
.
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