Skip to content

Instantly share code, notes, and snippets.

@maxsu
Last active December 5, 2020 23:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxsu/db9b0182b1d95225965a00b29684fce8 to your computer and use it in GitHub Desktop.
Save maxsu/db9b0182b1d95225965a00b29684fce8 to your computer and use it in GitHub Desktop.

[DRAFT] VERY rough syntax proposal. Suggestions welcome! [DRAFT]

Chunky Imports

Chunky Imports are designed to reduce verbosity and increase readability of import sections.

To do this, chunky imports extends Haskell 2010 import syntax in two ways:

I. Import Lists

These are a comma separated list of modules that share a import symbol.

This can reduces the line count and the number of import words in a document. Grouping imports into logical groups can make them more coherent and readable.

Example syntax:

import Prelude
import System.IO hiding (appendFile)
import List (intercalate, sort)

-- may become

import Prelude, System.IO hiding (appendFile), list(intercalate, sort)

II. Relative Import Lists

This is an import list whose imports additionally share some prefix module or namespace.

Single line form:

import foo.bar
import foo.bar.baz (qux)
import foo.quux hiding (corge)

--may become

import bar, bar.baz (qux), quux hiding (corge) from bar

Wildcard:

import foo
import foo.bar

--is equivalent to

import *, bar from foo

The wildcard will apear in our real world example below.

multiline form:

import	Data.Bifunctor
import	Data.Char
import	Data.Either
import	Data.Functor
import	Data.List		        (intercalate, sort)
import	Data.List.NonEmpty	        (NonEmpty ((:|)))
import	Data.Maybe
import	Data.String.Interpolate
import	Data.Text			(Text)
import	Data.Versions		        hiding (str)
import	Data.Void

-- becomes

import	Bifunctor, Char, Either, Functor, Maybe, Void,
        List                    (intercalate, sort)
        List.NonEmpty           (NonEmpty ((:|)))
        String.Interpolate
        Text			(Text)
        Versions		hiding (str)
        from Data

III. Real World Example

Here are two samples inspired by Maerwald et al's awesome ghcup. I leave it to the reader to decide if chunky imports provide an improvement.

Sample A (Before):

import	GHCup
import	GHCup.Download
import	GHCup.Errors
import	GHCup.Platform
import	GHCup.Requirements
import	GHCup.Types
import	GHCup.Utils
import	GHCup.Utils.File
import	GHCup.Utils.Logger
import	GHCup.Utils.MegaParsec
import	GHCup.Utils.Prelude
import	GHCup.Utils.String.QQ
import	GHCup.Version
import	Control.Exception.Safe
import	Control.Monad.Logger
import	Control.Monad.Reader
import	Control.Monad.Trans.Resource
import	Data.Bifunctor
import	Data.Char
import	Data.Either
import	Data.Functor
import	Data.List				(intercalate, sort)
import	Data.List.NonEmpty			(NonEmpty ((:|)))
import	Data.Maybe
import	Data.String.Interpolate
import	Data.Text				(Text)
import	Data.Versions				hiding (str)
import	Data.Void
import	GHC.IO.Encoding
import	Haskus.Utils.Variant.Excepts
import	HPath
import	HPath.IO
import	Language.Haskell.TH
import	Options.Applicative			hiding (style)
import	Options.Applicative.Help.Pretty (text)
import	Prelude					hiding (appendFile)
import	Safe
import	System.Console.Pretty
import	System.Environment
import	System.Exit
import	System.IO				hiding (appendFile)
import	Text.Read				hiding (lift)
import	URI.ByteString

Sample B (After):

import	*, Download, Errors, Platform, Requirements,
	Types, Utils, Version from GHCup
import	File, Logger, MegaParsec, Prelude, String.QQ
	from GHCup.Utils
import	Prelude		hiding	(appendFile)
import	Safe
import	Control.Exception.Safe
import	Logger, Reader, Trans.Resource from Control.Monad
import	Bifunctor, Data, Either, Functor, Maybe, Void,
        List            (intercalate, sort)
        List.NonEmpty  	(NonEmpty ((:|)))
        Text		Text)
        Versions	hiding (str)
        String.Interpolate
        from Data
import	GHC.IO.Encoding
import	Haskus.Utils.Variant.Excepts
import 	Hpath, Hpath.IO
import	Language.Haskell.TH
import	* hiding (style), Help.Pretty (text)
	from Options.Applicative
import	URI.ByteString
import	Text.Read	hiding	(lift)
import	Console.Pretty, Environment, Exit,
	IO 		hiding (appendFile)
	from System
Sample SLOC Import symbols Words Chars
A 42 42 102 1088
B 26 15 86 847
Delta -38% -64% -15% -22%

IV. Prior art and Open Questions

I have confirmed that the 2010 language standard does not provide compound impdecls. At first glance, no existing extension provides the feature or similar features. Template haskell may allow users to implement the feature for themselves, but I have not reviewed this extension yet.

My current open questions: Does template haskell let us define this facility? Where should I search for discussions of this or similar language features?

V. Dminuoso's Alternative: Why not place the horse before the cart?

Dminuoso suggested that having the "where" at the end of a list of imports is not very readable. This suggests an alternative form:

import	Control.Exception.Safe
import	GHC.IO.Encoding
import	Haskus.Utils.Variant.Excepts
import 	Hpath, Hpath.IO
import	Language.Haskell.TH
import	Prelude		hiding	(appendFile)
import	Safe
import	Text.Read	hiding	(lift)
import	URI.ByteString

from Ghcup import
	*, Download, Errors, Platform, Requirements,
	Types, Utils, Version

from GHCup.Utils import	
	File, Logger, MegaParsec, Prelude, String.QQ

from Control.Monad import
	Logger, Reader, Trans.Resource

from Data import
	Bifunctor, Data, Either, Functor, Maybe, Void,
        List            (intercalate, sort)
        List.NonEmpty  	(NonEmpty ((:|)))
        Text		(Text)
        Versions	hiding (str)
        String.Interpolate

from Options.Applicative import
	* hiding (style),
	Help.Pretty (text)

from System import
	Console.Pretty,
	Environment,
	Exit,
	IO hiding (appendFile)```
@mmynsted
Copy link

mmynsted commented Dec 5, 2020

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment