Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add implicit import proposal #500

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2c619e8
Add implicit import proposal
TristanCacqueray Apr 6, 2022
89fb09b
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 6, 2022
ccd66e2
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 6, 2022
06088e9
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 6, 2022
8f04394
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 6, 2022
a1c2ef0
Update based on comments
TristanCacqueray Apr 7, 2022
7335fea
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 8, 2022
c764186
Update proposals/0000-implicit-import.rst
TristanCacqueray Apr 8, 2022
39bb8e5
Update the motivation and specification
TristanCacqueray Apr 9, 2022
42e8ed3
Mention downsweep in the specification
TristanCacqueray Apr 10, 2022
40e3079
Update specification with Lexer usage
TristanCacqueray Apr 12, 2022
49ba7cd
Mention #283 in the alternatives
TristanCacqueray Apr 12, 2022
a34ba5d
Fix the header link
TristanCacqueray Apr 12, 2022
3a8dccc
Apply SPJ suggestions
TristanCacqueray Apr 14, 2022
cab22f7
Mention OCaml and Rust in the alternatives
TristanCacqueray Apr 14, 2022
827e97f
Mention Java in the alternatives
TristanCacqueray Apr 14, 2022
15d6d61
Update the specification and add another example
TristanCacqueray Apr 16, 2022
39e5c9b
Apply new suggestions and add more examples
TristanCacqueray Apr 18, 2022
aaa1cda
Add spacing and sub section for examples
TristanCacqueray Apr 18, 2022
cfe3d30
Slightly improve the example descriptions
TristanCacqueray Apr 19, 2022
d567b20
Mention merge conflicts in the negative effects
TristanCacqueray Apr 21, 2022
83270be
Develop the costs and drawbacks section
TristanCacqueray Apr 21, 2022
51d33d2
Address the remaining points
TristanCacqueray May 4, 2022
18b74d8
Update the Costs and Drawbacks
TristanCacqueray May 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions proposals/0000-implicit-import.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
Allow implicit qualified module import
======================================

.. author:: Tristan de Cacqueray
.. date-accepted:: Leave blank. This will be filled in when the proposal is accepted.
.. ticket-url:: Leave blank. This will eventually be filled with the
ticket URL which will track the progress of the
implementation of the feature.
.. implemented:: Leave blank. This will be filled in with the first GHC version which
implements the described feature.
.. highlight:: haskell
.. header:: This proposal is `discussed at this pull request <https://github.com/ghc-proposals/ghc-proposals/pull/497>`_.
.. contents::

The goal of this proposal is to enable direct access to any available module without requiring an import statement.
This removes an unnecessary restriction, making the language simpler.


Motivation
----------
The main purpose is to be able to directly use a package.
This is particularly useful for single use functions, such as ``Servant.serve``.
For example, this propose change would make the following program valid
(assuming a cabal file with build depends and default extensions):

::

module Main where

import Servant.API (Get, JSON, (:>))

type MyApi = "answer" :> Get '[JSON] Integer

server :: Servant.Server MyApi
server = pure 42

main :: IO ()
main = Network.Wai.Handler.Warp.run 8080 app
where
app :: Network.Wai.Application
app = Servant.serve (Data.Proxy.Proxy @MyApi) server


The status quo is not satisfactory because it requires adding explicit imports:

::

-- Without this proposal, these imports are required
import qualified Data.Proxy
import qualified Network.Wai
import qualified Network.Wai.Handler.Warp
import qualified Servant

Managing such imports has the following negative effects:

- It increases the file length.
- The author needs to jump to the top of the file each time a new module is used.
- It complicates code refactoring when moving a definition requires moving (or copying) its import.
TristanCacqueray marked this conversation as resolved.
Show resolved Hide resolved


Proposed Change Specification
-----------------------------
I propose an extension to enable implicit qualified imports.

When the ``ImplicitQualifiedImport`` language extension is enabled,
unknown fully qualified symbols are gracefully resolved early in the compilation pipeline by
injecting an implicit ``import qualified`` statement when necessary.
The pipeline might need an extra pass to collect missing imports.

GHCi already implements this feature thanks to the flag ``-fimplicit-import-qualified``,
but the flag does not seem to work with GHC.
Moreover the flag is not documented in ``ghc --show-options``, but it is accepted.
Thus this proposal deprecates the ``-fimplicit-import-qualified`` flag in favor of the
``-XImplicitQualifiedImport`` modifier, so that the behavior is consistent between GHC and GHCi.
TristanCacqueray marked this conversation as resolved.
Show resolved Hide resolved


Examples
--------
Here are some example functions that are often used locally and
it would be useful to call them without having to add an import statement:

- ``Control.Concurrent.threadDelay``
- ``Data.Char.isAlpha``
- ``Data.Foldable.traverse_``
- ``Data.Maybe.mapMaybe``
- ``Data.Set.fromList``
- ``Data.Text.pack``
- ``Debug.Trace.trace``
- ``System.Environment.getArgs``
- ``Text.Printf.printf``


Effect and Interactions
-----------------------
The proposed change enables using any module without requiring an import statement.

Interactions with existing language or compiler features:

- Fully qualified import with hidden declarations are not affected: with ``import Data.Maybe hiding (mapMaybe)``, using ``Data.Maybe.mapMaybe`` should not be valid.
TristanCacqueray marked this conversation as resolved.
Show resolved Hide resolved
- Modules available through multiple package will be disambiguated using the PackageImports extension.
- Only unknown fully qualified names will be affected.


Costs and Drawbacks
-------------------
TBD: estimate development and maintenance costs.

This extension may improve the language's learnability for novice users by:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that beginners usually don't use any language extensions, I don't think this would really affect beginners (unless it is enabled by default, of course). That would change however if this extension became part of a future GHC20XX language.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of a situation where this extension would not be useful, thus I'm hopeful it could be added to a future GHC20XX language.


- Reducing the length of code samples, and,
- Simplying new module usage, e.g. for one-off experiments and temporary annotations.

The main drawback is that the extension may reduce the readability of a module:
its external requirements would no longer be explicitely listed in the import section.
TristanCacqueray marked this conversation as resolved.
Show resolved Hide resolved


Alternatives
------------
Another helpful solution would be to enable local import, e.g. in a function definition.


Unresolved Questions
--------------------
TBD