-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A partial binary associative operator -- -- A partial semigroup is like a semigroup, but the operator is partial. -- We represent this in Haskell as a total function (<>?) :: a -- -> a -> Maybe a. -- -- The partial-semigroup-hedgehog companion package provides -- support for checking the partial semigroup associativity axiom using -- the hedgehog package. @package partial-semigroup @version 0.5.1.4 -- | A semigroup (Semigroup) is a set with a binary -- associative operation (<>). This module defines a -- partial semigroup (PartialSemigroup), a semigroup for -- which <> is not required to be defined over all inputs. module Data.PartialSemigroup -- | A PartialSemigroup is like a Semigroup, but with an -- operator returning Maybe a rather than a. -- -- For comparison: -- --
-- (<>) :: Semigroup a => a -> a -> a -- (<>?) :: PartialSemigroup a => a -> a -> Maybe a ---- --
-- x <> (y <> z) = (x <> y) <> z ---- -- with a slight modification to accommodate situations where -- <> is undefined. We may gain some insight into the -- connection between Semigroup and PartialSemigroup by -- rephrasing the partial semigroup associativity in terms of a partial -- <> operator thusly: -- -- For all x, y, z: -- -- class PartialSemigroup a (<>?) :: PartialSemigroup a => a -> a -> Maybe a infixr 6 <>? -- | A wrapper for Either where the PartialSemigroup operator -- is defined only over Left values. -- --
-- >>> AppendLeft (Left "ab") <>? AppendLeft (Left "cd")
-- Just (AppendLeft {unAppendLeft = Left "abcd"})
--
--
-- Anything else produces Nothing
--
-- -- >>> 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"] --newtype AppendLeft a b AppendLeft :: Either a b -> AppendLeft a b [unAppendLeft] :: AppendLeft a b -> Either a b -- | A wrapper for Either where the PartialSemigroup operator -- is defined only over Right values. -- --
-- >>> AppendRight (Right "ab") <>? AppendRight (Right "cd")
-- Just (AppendRight {unAppendRight = Right "abcd"})
--
--
-- Anything else produces Nothing
--
-- -- >>> 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"] --newtype AppendRight a b AppendRight :: Either a b -> AppendRight a b [unAppendRight] :: AppendRight a b -> Either a b -- | Apply a semigroup operation to any pairs of consecutive list elements -- where the semigroup operation is defined over them. -- --
-- >>> xs = [Left "a", Right "b", Right "c", Left "d", Left "e", Left "f"] -- -- >>> groupAndConcat xs -- [Left "a",Right "bc",Left "def"] --groupAndConcat :: PartialSemigroup a => [a] -> [a] -- | 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. -- --
-- >>> 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 --partialConcat :: PartialSemigroup a => [a] -> Maybe a -- | Like partialConcat, but for non-empty lists. -- --
-- >>> 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 --partialConcat1 :: PartialSemigroup a => NonEmpty a -> Maybe a -- |
-- >>> 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 --partialZip :: PartialSemigroup a => [a] -> [a] -> Maybe [a] -- | Like partialZip, but for non-empty lists. -- --
-- >>> 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 --partialZip1 :: PartialSemigroup a => NonEmpty a -> NonEmpty a -> Maybe (NonEmpty a) -- | A wrapper to turn any value with a Semigroup instance into a -- value with a PartialSemigroup instance whose <>? -- operator always returns Just. -- --
-- >>> Total "ab" <>? Total "cd"
-- Just (Total {unTotal = "abcd"})
--
--
-- -- >>> f = getProduct . unTotal -- -- >>> g = Total . Product -- -- >>> fmap f . partialConcat . fmap g $ [1..4] -- Just 24 --newtype Total a Total :: a -> Total a [unTotal] :: Total a -> a -- | A wrapper for Maybe with an error-propagating Semigroup. newtype Partial a Partial :: Maybe a -> Partial a [unPartial] :: Partial a -> Maybe a -- | A partial semigroup operation which always fails. newtype One a One :: a -> One a [theOne] :: One a -> a -- | A wrapper for Maybe whose partial semigroup operation fails -- when two Justs are combined. newtype AtMostOne a AtMostOne :: Maybe a -> AtMostOne a [theOneMaybe] :: AtMostOne a -> Maybe a instance GHC.Show.Show a => GHC.Show.Show (Data.PartialSemigroup.AtMostOne a) instance GHC.Read.Read a => GHC.Read.Read (Data.PartialSemigroup.AtMostOne a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.PartialSemigroup.AtMostOne a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.PartialSemigroup.AtMostOne a) instance GHC.Show.Show a => GHC.Show.Show (Data.PartialSemigroup.One a) instance GHC.Read.Read a => GHC.Read.Read (Data.PartialSemigroup.One a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.PartialSemigroup.One a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.PartialSemigroup.One a) instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Data.PartialSemigroup.AppendRight a b) instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (Data.PartialSemigroup.AppendRight a b) instance (GHC.Classes.Ord a, GHC.Classes.Ord b) => GHC.Classes.Ord (Data.PartialSemigroup.AppendRight a b) instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Data.PartialSemigroup.AppendRight a b) instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (Data.PartialSemigroup.AppendLeft a b) instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (Data.PartialSemigroup.AppendLeft a b) instance (GHC.Classes.Ord a, GHC.Classes.Ord b) => GHC.Classes.Ord (Data.PartialSemigroup.AppendLeft a b) instance (GHC.Classes.Eq a, GHC.Classes.Eq b) => GHC.Classes.Eq (Data.PartialSemigroup.AppendLeft a b) instance GHC.Show.Show a => GHC.Show.Show (Data.PartialSemigroup.Total a) instance GHC.Read.Read a => GHC.Read.Read (Data.PartialSemigroup.Total a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.PartialSemigroup.Total a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.PartialSemigroup.Total a) instance GHC.Show.Show a => GHC.Show.Show (Data.PartialSemigroup.Partial a) instance GHC.Read.Read a => GHC.Read.Read (Data.PartialSemigroup.Partial a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.PartialSemigroup.Partial a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.PartialSemigroup.Partial a) instance Data.PartialSemigroup.PartialSemigroup (Data.PartialSemigroup.AtMostOne a) instance Data.PartialSemigroup.PartialSemigroup (Data.PartialSemigroup.One a) instance Data.PartialSemigroup.PartialSemigroup b => Data.PartialSemigroup.PartialSemigroup (Data.PartialSemigroup.AppendRight a b) instance Data.PartialSemigroup.PartialSemigroup a => Data.PartialSemigroup.PartialSemigroup (Data.PartialSemigroup.AppendLeft a b) instance GHC.Base.Semigroup a => Data.PartialSemigroup.PartialSemigroup (Data.PartialSemigroup.Total a) instance Data.PartialSemigroup.PartialSemigroup a => GHC.Base.Semigroup (Data.PartialSemigroup.Partial a) instance Data.PartialSemigroup.PartialSemigroup () instance Data.PartialSemigroup.PartialSemigroup [a] instance GHC.Num.Num a => Data.PartialSemigroup.PartialSemigroup (Data.Semigroup.Internal.Sum a) instance GHC.Num.Num a => Data.PartialSemigroup.PartialSemigroup (Data.Semigroup.Internal.Product a) instance Data.PartialSemigroup.PartialSemigroup a => Data.PartialSemigroup.PartialSemigroup (Data.Functor.Identity.Identity a) instance (Data.PartialSemigroup.PartialSemigroup a, Data.PartialSemigroup.PartialSemigroup b) => Data.PartialSemigroup.PartialSemigroup (Data.Either.Either a b) instance (Data.PartialSemigroup.PartialSemigroup a, Data.PartialSemigroup.PartialSemigroup b) => Data.PartialSemigroup.PartialSemigroup (a, b) instance (Data.PartialSemigroup.PartialSemigroup a, Data.PartialSemigroup.PartialSemigroup b, Data.PartialSemigroup.PartialSemigroup c) => Data.PartialSemigroup.PartialSemigroup (a, b, c) instance Data.PartialSemigroup.PartialSemigroup a => Data.PartialSemigroup.PartialSemigroup (Control.Applicative.ZipList a) -- | If a type derives Generic and all of its fields have -- PartialSemigroup instances, you can get a -- PartialSemigroup for free using -- genericPartialSemigroupOp. -- --
-- >>> data T = A String (Either String String) | B String deriving (Generic, Show) ---- -- And then define its PartialSemigroup instance using -- genericPartialSemigroupOp. -- --
-- >>> instance PartialSemigroup T where (<>?) = genericPartialSemigroupOp ---- -- This gives us an implementation of <>? which combines -- values only if they have the same structure. -- --
-- >>> A "s" (Left "x") <>? A "t" (Left "y") -- Just (A "st" (Left "xy")) ---- --
-- >>> B "x" <>? B "y" -- Just (B "xy") ---- -- For values that do not have the same structure, -- <>? produces Nothing. -- --
-- >>> A "s" (Left "x") <>? A "t" (Right "y") -- Nothing ---- --
-- >>> A "x" (Left "y") <>? B "z" -- Nothing --module Data.PartialSemigroup.Generics genericPartialSemigroupOp :: (Generic a, PartialSemigroupRep (Rep a)) => a -> a -> Maybe a -- | The class of generic type Reps for which we can automatically -- derive PartialSemigroup: -- --
-- from . to ≡ id -- to . from ≡ id --class Generic a -- | A PartialSemigroup is like a Semigroup, but with an -- operator returning Maybe a rather than a. -- -- For comparison: -- --
-- (<>) :: Semigroup a => a -> a -> a -- (<>?) :: PartialSemigroup a => a -> a -> Maybe a ---- --
-- x <> (y <> z) = (x <> y) <> z ---- -- with a slight modification to accommodate situations where -- <> is undefined. We may gain some insight into the -- connection between Semigroup and PartialSemigroup by -- rephrasing the partial semigroup associativity in terms of a partial -- <> operator thusly: -- -- For all x, y, z: -- -- class PartialSemigroup a (<>?) :: PartialSemigroup a => a -> a -> Maybe a infixr 6 <>? instance Data.PartialSemigroup.PartialSemigroup a => Data.PartialSemigroup.Generics.PartialSemigroupRep (GHC.Generics.K1 i a) instance Data.PartialSemigroup.Generics.PartialSemigroupRep rep => Data.PartialSemigroup.Generics.PartialSemigroupRep (GHC.Generics.M1 i meta rep) instance (Data.PartialSemigroup.Generics.PartialSemigroupRep rep1, Data.PartialSemigroup.Generics.PartialSemigroupRep rep2) => Data.PartialSemigroup.Generics.PartialSemigroupRep (rep1 GHC.Generics.:*: rep2) instance (Data.PartialSemigroup.Generics.PartialSemigroupRep rep1, Data.PartialSemigroup.Generics.PartialSemigroupRep rep2) => Data.PartialSemigroup.Generics.PartialSemigroupRep (rep1 GHC.Generics.:+: rep2)