qualified imports, PVP and so on (Was: add new Data.Bits.Bits(bitZero) method)
Edward Kmett
ekmett at gmail.com
Fri Feb 28 20:23:01 UTC 2014
I just want to say thank you for writing this tool.
I may not agree with your interpretation of the PVP on this particular
issue, and will probably only use it on a couple of smaller packages that
have almost no imports, but at least putting code out there to help those
who do want to work in that style is a very helpful and valuable thing.
-Edward
On Fri, Feb 28, 2014 at 3:10 PM, Henning Thielemann <
schlepptop at henning-thielemann.de> wrote:
> I got distracted by writing a tool that checks consistency of package
> dependencies and import styles. It's not yet perfect, but usable:
>
> https://hackage.haskell.org/package/check-pvp
>
>
> Description:
> Check whether the version ranges used in the @Build-Depends@ field
> matches the style of module imports
> according to the Package Versioning Policy (PVP).
> See <http://www.haskell.org/haskellwiki/Package_versioning_policy>.
> The tool essentially looks for any dependency
> like @containers >=0.5 && <0.6@
> that allows the addition of identifiers to modules
> within the version range.
> Then it checks whether all module imports from @containers@
> are protected against name clashes
> that could be caused by addition of identifiers.
> .
> You must run the tool in a directory containing a Cabal package.
> .
> > $ check-pvp
> .
> This requires that the package is configured,
> since only then the association of packages to modules is known.
> If you want to run the tool on a non-configured package
> you may just check all imports for addition-proof style.
> .
> > $ check-pvp --include-all
> .
> It follows a detailed description of the procedure
> and the rationale behind it.
> .
> First the program classifies all dependencies
> in the Cabal file of the package.
> You can show all classifications with the @--classify-dependencies at option,
> otherwise only problematic dependencies are shown.
> .
> A dependency like @containers >=0.5.0.3 && <0.5.1@
> does not allow changes of the API of @containers@
> and thus the program does not check its imports.
> Clashing import abbreviations are an exception.
> .
> The dependency @containers >=0.5.1 && <0.6@
> requires more care when importing modules from @containers@
> and this is what the program is going to check next.
> This is the main purpose of the program!
> I warmly recommend this kind of dependency range
> since it greatly reduces the work
> to keep your package going together with its imported packages.
> .
> Dependencies like @containers >=0.5@ or @containers >=0.5 && <1@
> are always problematic,
> since within the specified version ranges identifier can disappear.
> There is no import style that protects against removed identifiers.
> .
> An inclusive upper bound as in @containers >=0.5 && <=0.6@
> will also cause a warning, because it is unnecessarily strict.
> If you know that @containers-0.6@ works for you,
> then @containers-0.6.0.1@ or @containers-0.6.1@ will also work,
> depending on your import style.
> A special case of inclusive upper bounds are specific versions
> like in @containers ==0.6 at .
> The argument for the warning remains the same.
> .
> Please note that the check of ranges
> is performed entirely on the package description.
> The program will not inspect the imported module contents.
> E.g. if you depend on @containers >=0.5 && <0.6@
> but import in a way that risks name clashes,
> then you may just extend the dependency to @containers >=0.5 && <0.6.1@
> in order to let the checker fall silent.
> If you use the dependency @containers >=0.5 && <0.6.1@
> then the checker expects that you have verified
> that your package works with all versions of kind @0.5.x@
> and the version @0.6.0 at .
> Other versions would then work, too,
> due to the constraints imposed by package versioning policy.
> .
> Let us now look at imports
> that must be protected against identifier additions.
> .
> The program may complain about a lax import.
> This means you have imported like
> .
> > import Data.Map as Map
> .
> Additions to @Data.Map@ may clash with other identifiers,
> thus you must import either
> .
> > import qualified Data.Map as Map
> .
> or
> .
> > import Data.Map (Map)
> .
> The program may complain about an open list of constructors as in
> .
> > import Data.Sequence (ViewL(..))
> .
> Additions of constructors to @ViewL@ may also conflict with other
> identifiers.
> You must instead import like
> .
> > import Data.Sequence (ViewL(EmptyL, (:<)))
> .
> or
> .
> > import qualified Data.Sequence as Seq
> .
> The program emits an error on clashing module abbreviations like
> .
> > import qualified Data.Map.Lazy as Map
> > import qualified Data.Map.Strict as Map
> .
> This error is raised
> whenever multiple modules are imported with the same abbreviation,
> where at least one module is open for additions.
> Our test is overly strict in the sense that it also blames
> .
> > import qualified Data.Map as Map
> > import qualified Data.Map as Map
> .
> but I think it is good idea to avoid redundant imports anyway.
> .
> Additionally you can enable a test for hiding imports
> with the @--pedantic@ option.
> The import
> .
> > import Data.Map hiding (insert)
> .
> is not bad in the sense of the PVP,
> but this way you depend on the existence of the identifier @insert@
> although you do not need it.
> If it is removed in a later version of @containers@,
> then your import breaks although you did not use the identifier.
> .
> Finally you can control what items are checked.
> First of all you can select the imports that are checked.
> Normally the imports are checked that belong to lax dependencies
> like @containers >=0.5 && <0.6 at .
> However this requires the package to be configured
> in order to know which import belongs to which dependency.
> E.g. @Data.Map@ belongs to @containers at .
> You can just check all imports for being addition-proof
> using the @--include-all@ option.
> Following you can write the options
> @--include-import@,
> @--exclude-import@,
> @--include-dependency@,
> @--exclude-dependency@
> that allow to additionally check or ignore imports
> from certain modules or packages.
> These modifiers are applied from left to right.
> E.g. @--exclude-import=Prelude@ will accept any import style for
> @Prelude@
> and @--exclude-dependency=foobar@ will ignore the package @foobar@,
> say, because it does not conform to the PVP.
> .
> Secondly, you may ignore certain modules or components of the package
> using the options
> @--exclude-module@,
> @--exclude-library@,
> @--exclude-executables@,
> @--exclude-testsuites@,
> @--exclude-benchmarks at .
> E.g. @--exclude-module=Paths_PKG@ will exclude the Paths module
> that is generated by Cabal.
> I assume that it will always be free of name clashes.
> .
> Known problems:
> .
> * The program cannot automatically filter out the @Paths@ module.
> .
> * The program cannot find and check preprocessed modules.
> .
> * The program may yield wrong results in the presence of Cabal
> conditions.
> .
> If this program proves to be useful
> it might eventually be integrated in the @check@ command of
> @cabal-install at .
> See <https://github.com/haskell/cabal/issues/1703>.
> .
> Alternative:
> If you want to allow exclusively large version ranges, i.e. @>=x.y &&
> <x.y+1@,
> then you may also add the option @-fwarn-missing-import-lists@
> to the @GHC-Options@ fields of your Cabal file.
> See <https://ghc.haskell.org/trac/ghc/ticket/4977>.
> Unfortunately there is no GHC warning on clashing module abbreviations.
> See <https://ghc.haskell.org/trac/ghc/ticket/4980>.
>
>
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20140228/98288fb9/attachment.html>
More information about the Libraries
mailing list