-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A type class for Matchable Functors. -- -- This package provides a type class Matchable, which -- represents zipMatch operation which can zip two values if -- these two have exactly same shape. @package matchable @version 0.1.2 module Data.Bimatchable -- | Containers that allows exact structural matching of two containers. -- -- Bimatchable is Bifunctor-version of -- Matchable. It can compare and zip containers with two -- parameters. class (Eq2 t, Bifunctor t) => Bimatchable t -- | bizipMatch is to zipMatch what bimap is to -- fmap. -- -- Decides if two structures match exactly. If they match, return zipped -- version of them. -- --
-- bizipMatch x y = Just z ---- -- holds if and only if both of -- --
-- x = bimap fst fst z -- y = bimap snd snd z ---- -- holds. Otherwise, bizipMatch x y = Nothing. -- --
-- >>> bizipMatch (Left 1) (Left 'a') -- Just (Left (1,'a')) -- -- >>> bizipMatch (Right 1) (Right False) -- Just (Right (1,False)) -- -- >>> bizipMatch (Left 1) (Right False) -- Nothing --bizipMatch :: Bimatchable t => t a b -> t a' b' -> Maybe (t (a, a') (b, b')) -- | bizipMatchWith is to zipMatchWith what bimap is -- to fmap. -- -- Match two structures. If they match, zip them with given functions -- (a -> a' -> Maybe a'') and (b -> b -> Maybe -- b''). Passed functions can make whole match failby returning -- Nothing. -- --
-- x :: t a b -- y :: t a' b' -- f :: a -> a' -> Maybe a'' -- g :: b -> b' -> Maybe b'' ---- -- bizipMatchWith must satisfy the following. -- --
x = bimap fst -- fst z
y = bimap snd snd z
bimap -- (uncurry f) (uncurry g) z = bimap Just Just w
-- zipMatch ta tb = Just tab ---- -- holds if and only if both of -- --
-- ta = fmap fst tab -- tb = fmap snd tab ---- -- holds. Otherwise, zipMatch ta tb = Nothing. -- -- For example, the type signature of zipMatch on the list -- Functor [] reads as follows: -- --
-- zipMatch :: [a] -> [b] -> Maybe [(a,b)] ---- -- zipMatch as bs returns Just (zip as bs) if the -- lengths of two given lists are same, and returns Nothing -- otherwise. -- --
-- >>> zipMatch [1, 2, 3] ['a', 'b', 'c'] -- Just [(1,'a'),(2,'b'),(3,'c')] -- -- >>> zipMatch [1, 2, 3] ['a', 'b'] -- Nothing --zipMatch :: Matchable t => t a -> t b -> Maybe (t (a, b)) -- | Match two structures. If they match, zip them with given function -- (a -> b -> Maybe c). Passed function can make whole -- match fail by returning Nothing. -- -- A definition of zipMatchWith must satisfy: -- --
ta = fmap fst tab
tb = fmap -- snd tab
fmap (uncurry f) tab = fmap Just -- tc
-- zipMatchWith f ta tb = traverse (uncurry f) tab ---- -- zipMatch can be defined in terms of zipMatchWith. -- And if t is also Traversable, zipMatchWith -- can be defined in terms of zipMatch. When you implement both -- of them by hand, keep their relation in the way the default -- implementation is. -- --
-- zipMatch = zipMatchWith (curry pure) -- zipMatchWith f ta tb = zipMatch ta tb >>= traverse (uncurry f) --zipMatchWith :: Matchable t => (a -> b -> Maybe c) -> t a -> t b -> Maybe (t c) -- |
-- zipzipMatch = zipMatchWith zipMatch --zipzipMatch :: (Matchable t, Matchable u) => t (u a) -> t (u b) -> Maybe (t (u (a, b))) -- | Matchable t implies Functor t. It is not recommended -- to implement fmap through this function, so it is named -- fmapRecovered but not fmapDefault. fmapRecovered :: Matchable t => (a -> b) -> t a -> t b -- | Matchable t implies Eq a => Eq (t a). eqDefault :: (Matchable t, Eq a) => t a -> t a -> Bool -- | Matchable t implies Eq1 t. liftEqDefault :: Matchable t => (a -> b -> Bool) -> t a -> t b -> Bool -- | An instance of Matchable can be implemened through GHC Generics. You -- only need to do two things: Make your type Functor and -- Generic1. -- --
-- >>> :set -XDeriveFunctor
--
-- >>> :set -XDeriveGeneric
--
-- >>> :{
-- data MyTree label a = Leaf a | Node label [MyTree label a]
-- deriving (Show, Read, Eq, Ord, Functor, Generic1)
-- :}
--
--
-- Then you can use genericZipMatchWith to implement
-- zipMatchWith method. You also need Eq1 instance, but
-- liftEqDefault is provided.
--
--
-- >>> :{
-- instance (Eq label) => Matchable (MyTree label) where
-- zipMatchWith = genericZipMatchWith
-- instance (Eq label) => Eq1 (MyTree label) where
-- liftEq = liftEqDefault
-- :}
--
--
-- -- >>> zipMatch (Node "foo" [Leaf 1, Leaf 2]) (Node "foo" [Leaf 'a', Leaf 'b']) -- Just (Node "foo" [Leaf (1,'a'),Leaf (2,'b')]) -- -- >>> zipMatch (Node "foo" [Leaf 1, Leaf 2]) (Node "bar" [Leaf 'a', Leaf 'b']) -- Nothing -- -- >>> zipMatch (Node "foo" [Leaf 1]) (Node "foo" []) -- Nothing --class Matchable' t -- | zipMatchWith via Generics. genericZipMatchWith :: (Generic1 t, Matchable' (Rep1 t)) => (a -> b -> Maybe c) -> t a -> t b -> Maybe (t c) instance GHC.Base.Functor (Data.Matchable.FillIn b) instance GHC.Base.Applicative (Data.Matchable.FillIn b) instance Data.Matchable.Matchable' GHC.Generics.V1 instance Data.Matchable.Matchable' GHC.Generics.U1 instance Data.Matchable.Matchable' GHC.Generics.Par1 instance Data.Matchable.Matchable f => Data.Matchable.Matchable' (GHC.Generics.Rec1 f) instance GHC.Classes.Eq c => Data.Matchable.Matchable' (GHC.Generics.K1 i c) instance Data.Matchable.Matchable' f => Data.Matchable.Matchable' (GHC.Generics.M1 i c f) instance (Data.Matchable.Matchable' f, Data.Matchable.Matchable' g) => Data.Matchable.Matchable' (f GHC.Generics.:+: g) instance (Data.Matchable.Matchable' f, Data.Matchable.Matchable' g) => Data.Matchable.Matchable' (f GHC.Generics.:*: g) instance (Data.Matchable.Matchable f, Data.Matchable.Matchable' g) => Data.Matchable.Matchable' (f GHC.Generics.:.: g) instance Data.Matchable.Matchable Data.Functor.Identity.Identity instance GHC.Classes.Eq k => Data.Matchable.Matchable (Data.Functor.Const.Const k) instance (Data.Matchable.Matchable f, Data.Matchable.Matchable g) => Data.Matchable.Matchable (Data.Functor.Product.Product f g) instance (Data.Matchable.Matchable f, Data.Matchable.Matchable g) => Data.Matchable.Matchable (Data.Functor.Sum.Sum f g) instance (Data.Matchable.Matchable f, Data.Matchable.Matchable g) => Data.Matchable.Matchable (Data.Functor.Compose.Compose f g) instance Data.Matchable.Matchable Data.Proxy.Proxy instance Data.Matchable.Matchable (Data.Tagged.Tagged t) instance Data.Matchable.Matchable GHC.Maybe.Maybe instance Data.Matchable.Matchable [] instance Data.Matchable.Matchable GHC.Base.NonEmpty instance GHC.Classes.Eq e => Data.Matchable.Matchable ((,) e) instance GHC.Classes.Eq e => Data.Matchable.Matchable (Data.Either.Either e) instance GHC.Classes.Eq k => Data.Matchable.Matchable (Data.Map.Internal.Map k) instance Data.Matchable.Matchable Data.IntMap.Internal.IntMap instance Data.Matchable.Matchable Data.Tree.Tree instance Data.Matchable.Matchable Data.Sequence.Internal.Seq instance Data.Matchable.Matchable Data.Vector.Vector instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k) => Data.Matchable.Matchable (Data.HashMap.Base.HashMap k)