-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Applicative maps -- -- This package provides a Defaultable type constructor that wraps -- any Map-like type to add an optional default value. Wrapping a -- Map-like type in this way permits a valid Applicative -- instance, so you can think of this as an "Applicative map" -- package. @package defaultable-map @version 1.0.2 -- | This module provides a Defaultable type constructor for -- extending Map-like types with a valid Applicative and -- Alternative instance. If you're looking for an -- "Applicative Map" then you are in the right place! -- -- The Defaultable type constructor can be used to wrap any -- Map-like, such as Data.Map.Map or -- Data.HashMap.HashMap. -- -- For convenience, this module also includes a concrete API wrapping -- Data.Map.Map since that's the most common case. -- If you are interested in a more general API that works with other -- Map types then check out the Defaultable.Map.Generalized -- module. -- -- The Applicative instance enables the use of the -- ApplicativeDo language extension. For example, suppose that -- you created the following three Defaultable Maps: -- --
-- firstNames, lastNames, handles :: Defaultable (Map Int) String -- firstNames = fromList [(0, "Gabriella" ), (1, "Oscar"), (2, "Edgar" ) ] -- lastNames = fromList [(0, "Gonzalez" ), (2, "Codd" ), (3, "Bryant" )] -- handles = fromList [(0, "GabriellaG439"), (1, "posco"), (3, "avibryant")] ---- -- Then you can use ApplicativeDo notation to create an "inner -- join" of these various maps, like this: -- --
-- >>> :set -XApplicativeDo
--
-- >>> do firstName <- firstNames; lastName <- lastNames; return (firstName, lastName)
-- Defaultable (fromList [(0,("Gabriella","Gonzalez")),(2,("Edgar","Codd"))]) Nothing
--
--
-- … and you can join as many of these maps as you want by adding
-- statements to these ApplicativeDo blocks:
--
--
-- {-# LANGUAGE ApplicativeDo #-}
--
-- innerJoins :: Defaultable (Map Int) (String, String, String)
-- innerJoins = do
-- firstName <- firstNames
-- lastName <- lastNames
-- handles <- handles
-- return (firstName, lastName, handles)
--
--
--
-- >>> innerJoins
-- Defaultable (fromList [(0,("Gabriella","Gonzalez","GabriellaG439"))]) Nothing
--
--
-- The Alternative instance for Defaultable is also
-- important, too, because you can use Alternative operations to
-- create "left/right joins" and something similar to an outer join, like
-- this:
--
-- -- leftJoin :: Defaultable (Map Int) (String, Maybe String) -- leftJoin = do -- firstName <- firstNames -- lastName <- optional lastNames -- return (firstName, lastName) -- -- rightJoin :: Defaultable (Map Int) (Maybe String, String) -- rightJoin = do -- firstName <- optional firstNames -- lastName <- lastNames -- return (firstName, lastName) -- -- -- similarToOuterJoin :: Defaultable (Map Int) (Maybe String, Maybe String) -- similarToOuterJoin = do -- firstName <- optional firstNames -- lastName <- optional lastNames -- return (firstName, lastName) ---- --
-- >>> leftJoin
-- Defaultable (fromList [(0,("Gabriella",Just "Gonzalez")),(1,("Oscar",Nothing)),(2,("Edgar",Just "Codd"))]) Nothing
--
-- >>> rightJoin
-- Defaultable (fromList [(0,(Just "Gabriella","Gonzalez")),(2,(Just "Edgar","Codd")),(3,(Nothing,"Bryant"))]) Nothing
--
-- >>> similarToOuterJoin
-- Defaultable (fromList [(0,(Just "Gabriella",Just "Gonzalez")),(1,(Just "Oscar",Nothing)),(2,(Just "Edgar",Just "Codd")),(3,(Nothing,Just "Bryant"))]) (Just (Nothing,Nothing))
--
--
-- You can also do more interesting multiway joins where any combiination
-- of the inputs may be optional:
--
-- -- complexJoin :: Defaultable (Map Int) (Maybe String, String, Maybe String) -- complexJoin = do -- firstName <- optional firstNames -- lastName <- lastNames -- handle <- optional handles -- return (firstName, lastName, handle) ---- --
-- >>> complexJoin -- Defaultable (fromList [(0,(Just "Gabriella","Gonzalez",Just "GabrielG439")),(2,(Just "Edgar","Codd",Nothing)),(3,(Nothing,"Bryant",Just "avibryant"))]) Nothing --module Defaultable.Map -- | A Defaultable type is a Map-like type that is extended -- with an optional default value. This default value can be used as a -- fallback if a lookup into the Map-like type does not find a -- matching key. -- -- The type variables are: -- --
-- Given: -- -- • mf :: map (a -> b) -- • mx :: map a -- • kf :: (a -> b) -> c -- • kx :: a -> c -- -- (mf <.> mx) <> fmap kf mf <> fmap kx mx -- = (mf <.> mx) <> fmap kx mx <> fmap kf mf ---- -- … where map is the first type parameter that implements -- Apply and Monoid. -- -- The intuition here is if that map is a Map-like type -- then we can think of those three expressions as having a set of keys -- associated with them, such that: -- --
-- Given: -- -- • keys :: map a -> Set key -- -- keys (mf <.> mx) = keys (fmap kf mf) `intersection` keys (fmap kx mx) ---- -- So normally the following equality would not be true: -- --
-- fmap kf mf <> fmap kx mx -- = fmap kx mx <> fmap kf mf ---- -- … because the result would change if there was a key collision. Then -- the order in which we union (<>) the two maps would -- change the result. -- -- However, if you union yet another map (mf <.> -- mx) that shadows the colliding keys then result remains the same. data Defaultable map value Defaultable :: map value -> Maybe value -> Defaultable map value -- | A Map from keys k to values a. -- -- The Semigroup operation for Map is union, which -- prefers values from the left operand. If m1 maps a key -- k to a value a1, and m2 maps the same key -- to a different value a2, then their union m1 <> -- m2 maps k to a1. data Map k a -- | Create a Defaultable Map from a Map -- --
-- >>> fromMap (Map.fromList [('A',1),('B',2),('B',3)])
-- Defaultable (fromList [('A',1),('B',3)]) Nothing
--
fromMap :: Map key value -> Defaultable (Map key) value
-- | Create a Defaultable Map from a single key-value pair
--
--
-- >>> singleton ('A', 1)
-- Defaultable (fromList [('A',1)]) Nothing
--
singleton :: (key, value) -> Defaultable (Map key) value
-- | Create a Defaultable Map from a list of key-value pairs
--
--
-- >>> fromList [('A',1),('B',2),('B',3)]
-- Defaultable (fromList [('A',1),('B',3)]) Nothing
--
fromList :: Ord key => [(key, value)] -> Defaultable (Map key) value
-- | Insert a key-value pair into a Defaultable Map
--
--
-- >>> let example = fromList [('A', 1)]
--
-- >>> insert ('B', 2) example
-- Defaultable (fromList [('A',1),('B',2)]) Nothing
--
-- >>> insert ('A', 0) example
-- Defaultable (fromList [('A',0)]) Nothing
--
--
-- For bulk updates, you should instead use
-- fromList/fromMap with (<|>):
--
--
-- >>> fromList [('A',0),('B', 2), ('C', 3)] <|> example
-- Defaultable (fromList [('A',0),('B',2),('C',3)]) Nothing
--
insert :: Ord key => (key, value) -> Defaultable (Map key) value -> Defaultable (Map key) value
-- | Add a default value to a Defaultable Map that is
-- returned as a fallback if a lookup cannot find a matching key
--
--
-- >>> let example = fromList [('A',1)] `withDefault` 2
--
-- >>> lookup 'A' example
-- Just 1
--
-- >>> lookup 'B' example
-- Just 2
--
withDefault :: Ord key => Defaultable (Map key) value -> value -> Defaultable (Map key) value
-- | Lookup the value at a key in the map
--
-- If the key is missing this falls back to returning the default value
-- if present
--
-- lookup is an Monad morphism, meaning that lookup
-- distributes over Monad operatiorns:
--
-- -- lookup (return x) = return x -- -- lookup (do x <- m; f x) = do x <- lookup m; lookup (f x) ---- -- lookup is also an Alternative morphism, meaning that -- lookup distributes over Alternative operations: -- --
-- lookup empty = empty -- -- lookup (l <|> r) = lookup l <|> lookup r ---- --
-- >>> let example = fromList [('A',1)]
--
-- >>> lookup 'A' example
-- Just 1
--
-- >>> lookup 'B' example
-- Nothing
--
-- >>> lookup 'B' (example `withDefault` 2)
-- Just 2
--
lookup :: Ord key => key -> Defaultable (Map key) value -> Maybe value
-- | Extract the underlying map from a Defaultable map
toMap :: Defaultable (Map key) value -> Map key value
-- | Extract the default value from a Defaultable map
toDefault :: Defaultable (Map key) value -> Maybe value
instance (Control.DeepSeq.NFData value, Control.DeepSeq.NFData (map value)) => Control.DeepSeq.NFData (Defaultable.Map.Defaultable map value)
instance Data.Traversable.Traversable map => Data.Traversable.Traversable (Defaultable.Map.Defaultable map)
instance (GHC.Show.Show value, GHC.Show.Show (map value)) => GHC.Show.Show (Defaultable.Map.Defaultable map value)
instance (GHC.Classes.Ord value, GHC.Classes.Ord (map value)) => GHC.Classes.Ord (Defaultable.Map.Defaultable map value)
instance GHC.Generics.Generic1 (Defaultable.Map.Defaultable map)
instance GHC.Generics.Generic (Defaultable.Map.Defaultable map value)
instance GHC.Base.Functor map => GHC.Base.Functor (Defaultable.Map.Defaultable map)
instance Data.Foldable.Foldable map => Data.Foldable.Foldable (Defaultable.Map.Defaultable map)
instance (GHC.Classes.Eq value, GHC.Classes.Eq (map value)) => GHC.Classes.Eq (Defaultable.Map.Defaultable map value)
instance (Data.Typeable.Internal.Typeable map, Data.Data.Data value, Data.Data.Data (map value)) => Data.Data.Data (Defaultable.Map.Defaultable map value)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a)) => Data.Functor.Bind.Class.Apply (Defaultable.Map.Defaultable map)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a)) => GHC.Base.Applicative (Defaultable.Map.Defaultable map)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a)) => Data.Functor.Alt.Alt (Defaultable.Map.Defaultable map)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a)) => GHC.Base.Alternative (Defaultable.Map.Defaultable map)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a), GHC.Base.Semigroup value) => GHC.Base.Semigroup (Defaultable.Map.Defaultable map value)
instance (Data.Functor.Bind.Class.Apply map, forall a. GHC.Base.Monoid (map a), GHC.Base.Monoid value) => GHC.Base.Monoid (Defaultable.Map.Defaultable map value)
-- | This module exports an API that is similar to Defaultable.Map,
-- except the utilities have been generalized further to work with any
-- Map-like type.
--
-- The only utility that cannot be generalized in this way is
-- lookup, so that is the only function missing from this module.
-- Other than the missing lookup function, this module is a
-- drop-in replacement for the Defaultable.Map module.
--
-- Also, keep in mind that these generalized utilities may have worse
-- type inference (especially you omit type annotations) and in some
-- cases might also be more inefficient. If this is an issue for you then
-- you'll need to create your own local module specializing these
-- utilities to your Map-like type of interest.
module Defaultable.Map.Generalized
-- | A Defaultable type is a Map-like type that is extended
-- with an optional default value. This default value can be used as a
-- fallback if a lookup into the Map-like type does not find a
-- matching key.
--
-- The type variables are:
--
-- -- Given: -- -- • mf :: map (a -> b) -- • mx :: map a -- • kf :: (a -> b) -> c -- • kx :: a -> c -- -- (mf <.> mx) <> fmap kf mf <> fmap kx mx -- = (mf <.> mx) <> fmap kx mx <> fmap kf mf ---- -- … where map is the first type parameter that implements -- Apply and Monoid. -- -- The intuition here is if that map is a Map-like type -- then we can think of those three expressions as having a set of keys -- associated with them, such that: -- --
-- Given: -- -- • keys :: map a -> Set key -- -- keys (mf <.> mx) = keys (fmap kf mf) `intersection` keys (fmap kx mx) ---- -- So normally the following equality would not be true: -- --
-- fmap kf mf <> fmap kx mx -- = fmap kx mx <> fmap kf mf ---- -- … because the result would change if there was a key collision. Then -- the order in which we union (<>) the two maps would -- change the result. -- -- However, if you union yet another map (mf <.> -- mx) that shadows the colliding keys then result remains the same. data Defaultable map value Defaultable :: map value -> Maybe value -> Defaultable map value -- | Generalized version of fromMap fromMap :: map value -> Defaultable map value -- | Generalized version of singleton singleton :: IsList (map value) => Item (map value) -> Defaultable map value -- | Generalized version of fromList fromList :: IsList (map value) => [Item (map value)] -> Defaultable map value -- | Generalized version of insert insert :: (IsList (map value), Apply map, forall a. Monoid (map a)) => Item (map value) -> Defaultable map value -> Defaultable map value -- | Generalized version of withDefault withDefault :: (Apply map, forall a. Monoid (map a)) => Defaultable map value -> value -> Defaultable map value -- | Generalized version of toMap toMap :: Defaultable map value -> map value -- | Generalized version of toDefault toDefault :: Defaultable map value -> Maybe value