    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Distribution.Package
    -- Copyright   :  Isaac Jones 2003-2004
    -- License     :  BSD3
    --
    -- Maintainer  :  cabal-devel@haskell.org
    -- Portability :  portable
    --
    -- Defines a package identifier along with a parser and pretty printer for it.
    -- 'PackageIdentifier's consist of a name and an exact version. It also defines
    -- a 'Dependency' data type. A dependency is a package name and a version
    -- range, like @\"foo >= 1.2 && < 2\"@.

    module Distribution.Package
      ( module Distribution.Types.AbiHash
      , module Distribution.Types.ComponentId
      , module Distribution.Types.PackageId
      , module Distribution.Types.UnitId
      , module Distribution.Types.Module
      , module Distribution.Types.PackageName
      , module Distribution.Types.PkgconfigName
      , module Distribution.Types.Dependency
      , Package(..), packageName, packageVersion
      , HasMungedPackageId(..), mungedName', mungedVersion'
      , HasUnitId(..)
      , PackageInstalled(..)
      ) where

    import Prelude ()
    import Distribution.Compat.Prelude

    import Distribution.Version
             ( Version )

    import Distribution.Types.AbiHash
    import Distribution.Types.ComponentId
    import Distribution.Types.Dependency
    import Distribution.Types.MungedPackageId
    import Distribution.Types.PackageId
    import Distribution.Types.UnitId
    import Distribution.Types.Module
    import Distribution.Types.MungedPackageName
    import Distribution.Types.PackageName
    import Distribution.Types.PkgconfigName

    -- | Class of things that have a 'PackageIdentifier'
    --
    -- Types in this class are all notions of a package. This allows us to have
    -- different types for the different phases that packages go though, from
    -- simple name\/id, package description, configured or installed packages.
    --
    -- Not all kinds of packages can be uniquely identified by a
    -- 'PackageIdentifier'. In particular, installed packages cannot, there may be
    -- many installed instances of the same source package.
    --
    class Package pkg where
      packageId  :: pkg -> PackageIdentifier

    mungedName'    :: HasMungedPackageId pkg => pkg -> MungedPackageName
    mungedName' :: forall pkg. HasMungedPackageId pkg => pkg -> MungedPackageName
    mungedName'     = MungedPackageId -> MungedPackageName
    mungedName    (MungedPackageId -> MungedPackageName)
    -> (pkg -> MungedPackageId) -> pkg -> MungedPackageName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . pkg -> MungedPackageId
    forall pkg. HasMungedPackageId pkg => pkg -> MungedPackageId
    mungedId

    mungedVersion' :: HasMungedPackageId munged => munged -> Version
    mungedVersion' :: forall munged. HasMungedPackageId munged => munged -> Version
    mungedVersion'  = MungedPackageId -> Version
    mungedVersion (MungedPackageId -> Version)
    -> (munged -> MungedPackageId) -> munged -> Version
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . munged -> MungedPackageId
    forall pkg. HasMungedPackageId pkg => pkg -> MungedPackageId
    mungedId

    class HasMungedPackageId pkg where
      mungedId :: pkg -> MungedPackageId

    instance Package PackageIdentifier where
      packageId :: PackageIdentifier -> PackageIdentifier
    packageId = PackageIdentifier -> PackageIdentifier
    forall a. a -> a
    id

    packageName    :: Package pkg => pkg -> PackageName
    packageName :: forall pkg. Package pkg => pkg -> PackageName
    packageName     = PackageIdentifier -> PackageName
    pkgName    (PackageIdentifier -> PackageName)
    -> (pkg -> PackageIdentifier) -> pkg -> PackageName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . pkg -> PackageIdentifier
    forall pkg. Package pkg => pkg -> PackageIdentifier
    packageId

    packageVersion :: Package pkg => pkg -> Version
    packageVersion :: forall pkg. Package pkg => pkg -> Version
    packageVersion  = PackageIdentifier -> Version
    pkgVersion (PackageIdentifier -> Version)
    -> (pkg -> PackageIdentifier) -> pkg -> Version
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . pkg -> PackageIdentifier
    forall pkg. Package pkg => pkg -> PackageIdentifier
    packageId

    instance HasMungedPackageId MungedPackageId where
      mungedId :: MungedPackageId -> MungedPackageId
    mungedId = MungedPackageId -> MungedPackageId
    forall a. a -> a
    id

    -- | Packages that have an installed unit ID
    class Package pkg => HasUnitId pkg where
      installedUnitId :: pkg -> UnitId

    -- | Class of installed packages.
    --
    -- The primary data type which is an instance of this package is
    -- 'InstalledPackageInfo', but when we are doing install plans in Cabal install
    -- we may have other, installed package-like things which contain more metadata.
    -- Installed packages have exact dependencies 'installedDepends'.
    class (HasUnitId pkg) => PackageInstalled pkg where
      installedDepends :: pkg -> [UnitId]