Skip to content

Commit

Permalink
Turn 'configPrograms' field into a 'Last'-monoid
Browse files Browse the repository at this point in the history
This implements the suggestions mentioned at
haskell#3169 (comment)

The main benefit of this change is turning 'ConfigFlags' into a uniform
product-type suitable for generic derivation of pointwise
`Semigroup`/`Monoid` instances.

NB: This changes the `Binary` serialisation of `ConfigFlags` since there's
now an additional `Maybe` inserted in `configPrograms`'s type
  • Loading branch information
hvr committed Feb 27, 2016
1 parent c25c974 commit 62c3aa6
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 10 deletions.
32 changes: 29 additions & 3 deletions Cabal/Distribution/Compat/Semigroup.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeOperators #-}

-- | Compatibility layer for "Data.Semigroup"
module Distribution.Compat.Semigroup
Expand All @@ -9,10 +11,15 @@ module Distribution.Compat.Semigroup
, All(..)
, Any(..)

, Last'(..)

, gmappend
, gmempty
) where

import Distribution.Compat.Binary (Binary)

import Control.Applicative as App
import GHC.Generics
#if __GLASGOW_HASKELL__ >= 711
-- Data.Semigroup is available since GHC 8.0/base-4.9
Expand Down Expand Up @@ -93,6 +100,25 @@ instance Ord k => Semigroup (Map k v) where
(<>) = mappend
#endif

-- | Cabal's own 'Data.Monoid.Last' copy to avoid requiring an orphan
-- 'Binary' instance.
--
-- Once the oldest `binary` version we support provides a 'Binary'
-- instance for 'Data.Monoid.Last' we can remove this one here.
--
-- NB: 'Data.Semigroup.Last' is defined differently and not a 'Monoid'
newtype Last' a = Last' { getLast' :: Maybe a }
deriving (Eq, Ord, Read, Show, Binary,
Functor, App.Applicative, Generic)

instance Semigroup (Last' a) where
x <> Last' Nothing = x
_ <> x = x

instance Monoid (Last' a) where
mempty = Last' Nothing
mappend = (<>)

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Stolen from Edward Kmett's BSD3-licensed `semigroups` package
Expand Down
2 changes: 1 addition & 1 deletion Cabal/Distribution/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ getBuildConfig hooks verbosity distPref = do
-- of a configure run:
configPrograms = restoreProgramConfiguration
(builtinPrograms ++ hookedPrograms hooks)
(configPrograms cFlags),
`fmap` configPrograms cFlags,

-- Use the current, not saved verbosity level:
configVerbosity = Flag verbosity
Expand Down
8 changes: 7 additions & 1 deletion Cabal/Distribution/Simple/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ import Text.PrettyPrint
, quotes, punctuate, nest, sep, hsep )
import Distribution.Compat.Environment ( lookupEnv )
import Distribution.Compat.Exception ( catchExit, catchIO )
import Distribution.Compat.Semigroup ( Last'(..) )

-- | The errors that can be thrown when reading the @setup-config@ file.
data ConfigStateFileError
Expand Down Expand Up @@ -346,7 +347,7 @@ configure (pkg_descr0', pbi) cfg = do
(flagToMaybe (configHcFlavor cfg))
(flagToMaybe (configHcPath cfg))
(flagToMaybe (configHcPkg cfg))
(mkProgramsConfig cfg (configPrograms cfg))
(mkProgramsConfig cfg (configPrograms' cfg))
(lessVerbose verbosity)

-- The InstalledPackageIndex of all installed packages
Expand Down Expand Up @@ -686,6 +687,11 @@ configure (pkg_descr0', pbi) cfg = do
return (Flag ProfDetailDefault)
checkProfDetail other = return other

-- | More convenient version of 'configPrograms'. Results in an
-- 'error' if internal invariant is violated.
configPrograms' :: ConfigFlags -> ProgramConfiguration
configPrograms' = maybe (error "FIXME: remove configPrograms") id . getLast' . configPrograms

mkProgramsConfig :: ConfigFlags -> ProgramConfiguration -> ProgramConfiguration
mkProgramsConfig cfg initialProgramsConfig = programsConfig
where
Expand Down
10 changes: 5 additions & 5 deletions Cabal/Distribution/Simple/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,8 @@ data ConfigFlags = ConfigFlags {
-- because the type of configure is constrained by the UserHooks.
-- when we change UserHooks next we should pass the initial
-- ProgramConfiguration directly and not via ConfigFlags
configPrograms :: ProgramConfiguration, -- ^All programs that cabal may
-- run
configPrograms :: Last' ProgramConfiguration, -- ^All programs that
-- @cabal@ may run

configProgramPaths :: [(String, FilePath)], -- ^user specified programs paths
configProgramArgs :: [(String, [String])], -- ^user specified programs args
Expand Down Expand Up @@ -404,7 +404,7 @@ configAbsolutePaths f =

defaultConfigFlags :: ProgramConfiguration -> ConfigFlags
defaultConfigFlags progConf = emptyConfigFlags {
configPrograms = progConf,
configPrograms = pure progConf,
configHcFlavor = maybe NoFlag Flag defaultCompilerFlavor,
configVanillaLib = Flag True,
configProfLib = NoFlag,
Expand Down Expand Up @@ -812,7 +812,7 @@ emptyConfigFlags = mempty

instance Monoid ConfigFlags where
mempty = ConfigFlags {
configPrograms = error "FIXME: remove configPrograms",
configPrograms = mempty,
configProgramPaths = mempty,
configProgramArgs = mempty,
configProgramPathExtra = mempty,
Expand Down Expand Up @@ -862,7 +862,7 @@ instance Monoid ConfigFlags where

instance Semigroup ConfigFlags where
a <> b = ConfigFlags {
configPrograms = configPrograms b,
configPrograms = combine configPrograms,
configProgramPaths = combine configProgramPaths,
configProgramArgs = combine configProgramArgs,
configProgramPathExtra = combine configProgramPathExtra,
Expand Down

0 comments on commit 62c3aa6

Please sign in to comment.