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

Recommended set of language extensions? #9

Closed
snoyberg opened this issue Jan 3, 2018 · 15 comments
Closed

Recommended set of language extensions? #9

snoyberg opened this issue Jan 3, 2018 · 15 comments

Comments

@snoyberg
Copy link
Collaborator

snoyberg commented Jan 3, 2018

And should we advise setting these in the package.yaml file vs LANGUAGE pragmas.

@kerscher
Copy link
Contributor

kerscher commented Jan 3, 2018

I think I’m a minority opinion, but I always enable those I consider “safe” package-wide:

  • NoImplicitPrelude (with classy-prelude, classy-prelude-conduit, foundation etc)
  • OverloadedStrings
  • OverloadedLists
  • LambdaCase
  • GADTSyntax
  • RankNTypes
  • ScopedTypeVariables
  • DeriveGeneric
  • TupleSections
  • BangPatterns
  • MultiParamTypeClasses
  • FlexibleInstances
  • FlexibleContexts
  • MultiWayIf
  • TypeFamilies
  • TypeOperators
  • FunctionalDependencies
  • DisambiguateRecordFields
  • MonadComprehensions
  • BinaryLiterals
  • RecursiveDo
  • ParallelListComp
  • PartialTypeSignatures
  • RecordWildCards
  • PatternSynonyms
  • EmptyCase
  • InstanceSigs
  • KindSignatures
  • DeriveFunctor
  • DeriveFoldable
  • DeriveTraversable
  • ConstraintKinds
  • ExplicitNamespaces

@kerscher
Copy link
Contributor

kerscher commented Jan 3, 2018

Once there is a rio template on stack new, any selected choices could probably go immediately there, and a recommendation is to just stack new PACKAGE rio.

@NorfairKing
Copy link

I like the idea of not writing many language pragmas as well.
Afterall, not having to manually add dependencies is very similar..

@snoyberg
Copy link
Collaborator Author

snoyberg commented Jan 4, 2018

In addition to the question of which language extensions, is whether it's acceptable to put the language extensions in the package.yaml/cabal file instead of in each module. There's been tooling pushback on this in the past (I think from @nh2, but I'm not sure I'm remembering correctly).

@nh2
Copy link

nh2 commented Jan 4, 2018

Yes that would be me.

haskell-source-exts (and tools built on it) and ghci do not understand cabal files.

If you put pragmas into cabal files, you cannot trivially use some of these tools (e.g. for generating simpe ctags, you only need to parse, which you can do per-file without having to implement any support for cabal), or quickly load a couple of different modules from different packages into one ghci by using the -i flag (because -X flags to ghci are global).

Without the haskell-source-exts programs I could live, or force them to implement support by depending on the Cabal package (and the extra maintenance effort to keep up with the changes in that), but the no-manual-ghci problem is a real killer.

@nh2
Copy link

nh2 commented Jan 4, 2018

I guess I should also bring in some form of bold statement:

I would happily choose spending a few seconds at the creation of each .hs file (and forcing coworkers and community members to do so) over manually re-creating this work each time I have to do some ghci based surgery, and then not commit this work (of putting the pragmas in each file).

@kerscher
Copy link
Contributor

kerscher commented Jan 5, 2018

Then we can put something like this on the template, and provide for some editors a snippet for the few seconds mentioned:

{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, OverloadedLists,
  LambdaCase, GADTSyntax, RankNTypes, ScopedTypeVariables,
  DeriveGeneric, TupleSections, BangPatterns, MultiParamTypeClasses,
  FlexibleInstances, FlexibleContexts, MultiWayIf, TypeFamilies,
  TypeOperators, FunctionalDependencies, DisambiguateRecordFields,
  MonadComprehensions, BinaryLiterals, RecursiveDo, ParallelListComp,
  PartialTypeSignatures, RecordWildCards, PatternSynonyms, EmptyCase,
  InstanceSigs, KindSignatures, DeriveFunctor, DeriveFoldable,
  DeriveTraversable, ConstraintKinds, ExplicitNamespaces #-}

module SomeModule
  (
  ) where

import RIO

@nh2
Copy link

nh2 commented Jan 6, 2018

Yeah I guess that'd do.

One might debate whether it should be like that or one-per-line which makes diffs look better, but for the purpose of ghci, that doens't matter.

We should also consider that some of these proposed ones might be controversial. For example, some consider RecordWildCards an antipattern that makes things less readable (though that is about the usage of the {..}, not of the language extension being enabled; it could still be enabled but one might recommend against using it in many cases), and OverloadedLists mght be too (it can make code compile that you don't want to compile).

@kerscher
Copy link
Contributor

kerscher commented Jan 8, 2018

I’d say aggregate for the “commonly agreed-upon subset” and one per line for others, then you have the most compact representation that is amenable to good workflow.
In theory there would never be a diff for the topmost value that defines what Haskell201X would.

@mgsloan
Copy link
Contributor

mgsloan commented Jan 18, 2018

Oops, I didn't have a watch set on this repo yet, so only just saw this issue. Until ghci can properly load multiple packages at once, we should not recommend any default extensions that are known to cause some code to no longer compile. There's a list here: https://github.com/commercialhaskell/stack/blob/864831f8f2d4c91e5989f2cbfbe3769c03946e0d/src/Stack/Ghci.hs#L635

So, this would mean removing OverloadedStrings, NoImplicitPrelude, and also GADTs and TypeFamilies (anything that implies MonoLocalBinds). Ugly I know, hopefully https://ghc.haskell.org/trac/ghc/ticket/10827 gets addressed sometime. Even addressing it only for extensions would be nice.

I guess the alternative approach would be to convert libraries to using these, but that's hard if you ever want to load older packages into your ghci along with newer.

@mgsloan
Copy link
Contributor

mgsloan commented Jan 18, 2018

Another reason to not include OverloadedStrings / OverloadedLists is that they break Paths_ modules, and hpack includes them automatically: commercialhaskell/stack#3789

@akhra
Copy link
Collaborator

akhra commented Jan 18, 2018

For what it's worth, I've also run into stylish-haskell choking on files that use an extension's syntax without declaring it at the top (when invoked via vscode+Haskero, anyway).

@Tehnix
Copy link

Tehnix commented Jan 18, 2018

Would a middle ground be to include in the stack new PACKAGE rio template, a .ghci which sets the same extensions that would be set in package.yaml/cabal? Similarly .stylish-haskell.yaml also supports setting default language extensions—or is it too much to assume people would setup projects using the stack templates?

I would personally hate to have that long list of extensions in the top, but I don't know if the other tooling, such as haskell-source-exts, would be able to use that?

@nh2
Copy link

nh2 commented Jan 18, 2018

Would a middle ground be to include in the stack new PACKAGE rio template, a .ghci which sets the same extensions that would be set in package.yaml/cabal?

I don't think so, because .ghci files don't reliably work inside version control. E.g. git resets the permissions of it on checkout, and ghci refuses to use .ghci files if the permissions are not as it likes.

@snoyberg
Copy link
Collaborator Author

snoyberg commented Feb 9, 2018

I think we're stuck with language pragmas in the modules themselves for now. The list is already documented, and in the future we can include that list in a template. Closing as complete.

@snoyberg snoyberg closed this as completed Feb 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants