From 601966737ae0b41c5c1b3d532ae49c7a8be8faa8 Mon Sep 17 00:00:00 2001 From: Edsko de Vries <edsko@well-typed.com> Date: Tue, 24 Mar 2015 10:36:53 +0000 Subject: [PATCH] Introduce ComponentDeps The ComponentDeps datatype will give us fine-grained information about the dependencies of a package's components. This commit just introduces the datatype, we don't use it anywhere yet. --- .../Distribution/Client/ComponentDeps.hs | 113 ++++++++++++++++++ cabal-install/cabal-install.cabal | 1 + 2 files changed, 114 insertions(+) create mode 100644 cabal-install/Distribution/Client/ComponentDeps.hs diff --git a/cabal-install/Distribution/Client/ComponentDeps.hs b/cabal-install/Distribution/Client/ComponentDeps.hs new file mode 100644 index 0000000000..f6ee4d9a77 --- /dev/null +++ b/cabal-install/Distribution/Client/ComponentDeps.hs @@ -0,0 +1,113 @@ +-- | Fine-grained package dependencies +-- +-- Like many others, this module is meant to be "double-imported": +-- +-- > import Distribution.Client.ComponentDeps ( +-- > Component +-- > , ComponentDep +-- > , ComponentDeps +-- > ) +-- > import qualified Distribution.Client.ComponentDeps as CD +{-# LANGUAGE CPP #-} +{-# LANGUAGE DeriveFunctor #-} +module Distribution.Client.ComponentDeps ( + -- * Fine-grained package dependencies + Component(..) + , ComponentDep + , ComponentDeps -- opaque + -- ** Constructing ComponentDeps + , empty + , fromList + , singleton + , insert + , fromLibraryDeps + , fromInstalled + -- ** Deconstructing ComponentDeps + , toList + , flatDeps + ) where + +import Data.Map (Map) +import qualified Data.Map as Map +import Data.Foldable (fold) + +#if !MIN_VERSION_base(4,8,0) +import Data.Foldable (Foldable(foldMap)) +import Data.Monoid (Monoid(..)) +import Data.Traversable (Traversable(traverse)) +#endif + +{------------------------------------------------------------------------------- + Types +-------------------------------------------------------------------------------} + +-- | Component of a package +data Component = + ComponentLib + | ComponentExe String + | ComponentTest String + | ComponentBench String + deriving (Show, Eq, Ord) + +-- | Dependency for a single component +type ComponentDep a = (Component, a) + +-- | Fine-grained dependencies for a package +newtype ComponentDeps a = ComponentDeps { unComponentDeps :: Map Component a } + deriving (Show, Functor, Eq, Ord) + +instance Monoid a => Monoid (ComponentDeps a) where + mempty = + ComponentDeps Map.empty + (ComponentDeps d) `mappend` (ComponentDeps d') = + ComponentDeps (Map.unionWith mappend d d') + +instance Foldable ComponentDeps where + foldMap f = foldMap f . unComponentDeps + +instance Traversable ComponentDeps where + traverse f = fmap ComponentDeps . traverse f . unComponentDeps + +{------------------------------------------------------------------------------- + Construction +-------------------------------------------------------------------------------} + +empty :: ComponentDeps a +empty = ComponentDeps $ Map.empty + +fromList :: Monoid a => [ComponentDep a] -> ComponentDeps a +fromList = ComponentDeps . Map.fromListWith mappend + +singleton :: Component -> a -> ComponentDeps a +singleton comp = ComponentDeps . Map.singleton comp + +insert :: Monoid a => Component -> a -> ComponentDeps a -> ComponentDeps a +insert comp a = ComponentDeps . Map.alter aux comp . unComponentDeps + where + aux Nothing = Just a + aux (Just a') = Just $ a `mappend` a' + +-- | ComponentDeps containing library dependencies only +fromLibraryDeps :: a -> ComponentDeps a +fromLibraryDeps = singleton ComponentLib + +-- | ComponentDeps for installed packages +-- +-- We assume that installed packages only record their library dependencies +fromInstalled :: a -> ComponentDeps a +fromInstalled = fromLibraryDeps + +{------------------------------------------------------------------------------- + Deconstruction +-------------------------------------------------------------------------------} + +toList :: ComponentDeps a -> [ComponentDep a] +toList = Map.toList . unComponentDeps + +-- | All dependencies of a package +-- +-- This is just a synonym for 'fold', but perhaps a use of 'flatDeps' is more +-- obvious than a use of 'fold', and moreover this avoids introducing lots of +-- @#ifdef@s for 7.10 just for the use of 'fold'. +flatDeps :: Monoid a => ComponentDeps a -> a +flatDeps = fold diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal index 954644b8a0..8e54000c37 100644 --- a/cabal-install/cabal-install.cabal +++ b/cabal-install/cabal-install.cabal @@ -51,6 +51,7 @@ executable cabal Distribution.Client.BuildReports.Types Distribution.Client.BuildReports.Upload Distribution.Client.Check + Distribution.Client.ComponentDeps Distribution.Client.Config Distribution.Client.Configure Distribution.Client.Dependency -- GitLab