├── .gitignore ├── .travis.yml ├── GRC.rst ├── Makefile ├── README.rst ├── acceptance.rst ├── committee.rst ├── conf.py ├── index.rst ├── inline-comment.png ├── principles.rst ├── proposals ├── 0000-template.md ├── 0000-template.rst ├── 0001-proposal-process.rst ├── 0002-overloaded-record-fields.rst ├── 0003-levity-polymorphism.rst ├── 0004-hexFloats.rst ├── 0005-bidir-constr-sigs.rst ├── 0006-deriving-empty.rst ├── 0007-instance-foralls.rst ├── 0008-type-infix.rst ├── 0009-numeric-underscores.rst ├── 0010-block-arguments.rst ├── 0011-deprecate-stm-invariants.rst ├── 0012-Wall-uni-patterns.rst ├── 0013-unlifted-newtypes.rst ├── 0014-small-primitives.rst ├── 0015-type-level-type-applications.rst ├── 0016-as-patterns-synonyms.rst ├── 0017-source-plugins.rst ├── 0018-quantified-constraints.rst ├── 0019-constraint-vs-type.rst ├── 0020-no-type-in-type.rst ├── 0021-unlifted-array.rst ├── 0022-plugin-recompilation.rst ├── 0023-deriving-via.rst ├── 0023-overloaded-record-fields.rst ├── 0024-no-kind-vars.rst ├── 0025-resize-boxed.rst ├── 0026-explicit-specificity.rst ├── 0027-atomicModifyMutVar.rst ├── 0028-deprecating-exports-proposal.rst ├── 0029-levity-polymorphism.rst ├── 0029-scoped-type-variables-types.rst ├── 0030-remove-star-kind.rst ├── 0031-type-applications-in-patterns.rst ├── 0032-constraint-vs-type.rst ├── 0032-type-data.rst ├── 0033-unbanged-strict-patterns.rst ├── 0034-stable-names.rst ├── 0035-forall-arrow.rst ├── 0035-unbanged-strict-patterns.rst ├── 0036-kind-signatures.rst ├── 0037-hexFloats.rst ├── 0037-unpack-pragma-precedence.rst ├── 0038-fail-rebindable-with-overloaded-strings.rst ├── 0039-dot-type-operator.rst ├── 0040-unrestricted-overloadedlabels.rst ├── 0041-ghci-instances.rst ├── 0042-bidir-constr-sigs.rst ├── 0042-record-set-field.rst ├── 0043-forall-keyword.rst ├── 0044-minimal-should-warn-extras.rst ├── 0045-pointer-rep.rst ├── 0046-scc-parsing.rst ├── 0047-levity-polymorphic-lift.rst ├── 0048-printing-foralls.rst ├── 0049-module-qualified-syntax.rst ├── 0050-type-lambda.rst ├── 0051-function-result-sigs.rst ├── 0052-threaded-by-default.rst ├── 0053-type-annotated-quoters.rst ├── 0054-AmbiguousType-pragma.rst ├── 0054-kind-signatures.rst ├── 0055-instance-foralls.rst ├── 0063-deriving-empty.rst ├── 0065-type-infix.rst ├── 0071-Wall-uni-patterns.rst ├── 0074-small-primitives.rst ├── 0076-numeric-underscores.rst ├── 0077-deprecate-stm-invariants.rst ├── 0080-type-level-type-applications.rst ├── 0081-forall-arrow.rst ├── 0083-no-type-in-type.rst ├── 0090-block-arguments.rst ├── 0094-as-patterns-synonyms.rst ├── 0098-unlifted-newtypes.rst ├── 0099-explicit-specificity.rst ├── 0103-no-kind-vars.rst ├── 0106-type-data.rst ├── 0107-source-plugins.rst ├── 0108-plugin-recompilation.rst ├── 0109-quantified-constraints.rst ├── 0111-linear-types.rst ├── 0112-unlifted-array.rst ├── 0120-deriving-via.rst ├── 0121-resize-boxed.rst ├── 0125-type-annotated-quoters.rst ├── 0126-type-applications-in-patterns.rst ├── 0128-scoped-type-variables-types.rst ├── 0134-deprecating-exports-proposal.rst ├── 0143-remove-star-kind.rst ├── 0149-atomicModifyMutVar.rst ├── 0155-type-lambda.rst ├── 0158-record-set-field.rst ├── 0160-no-toplevel-field-selectors.rst ├── 0163-stable-names.rst ├── 0166-ghci-instances.rst ├── 0168-fail-rebindable-with-overloaded-strings.rst ├── 0170-unrestricted-overloadedlabels.rst ├── 0173-dot-type-operator.rst ├── 0174-unpack-pragma-precedence.rst ├── 0176-scc-parsing.rst ├── 0179-printing-foralls.rst ├── 0190-module-qualified-syntax.rst ├── 0193-forall-keyword.rst ├── 0195-code-texp.rst ├── 0203-pointer-rep.rst ├── 0209-levity-polymorphic-lift.rst ├── 0210-minimal-should-warn-extras.rst ├── 0216-qualified-do.rst ├── 0228-function-result-sigs.rst ├── 0229-whitespace-bang-patterns.rst ├── 0232-AmbiguousType-pragma.rst ├── 0240-threaded-by-default.rst ├── 0242-unsaturated-type-families.rst ├── 0246-overloaded-bracket.rst ├── 0265-unlifted-datatypes.rst ├── 0274-quick-look-impredicativity.rst ├── 0277-winapi-callconv.rst ├── 0281-visible-forall.rst ├── 0282-record-dot-syntax.rst ├── 0285-no-implicit-binds.rst ├── 0287-simplify-subsumption.rst ├── 0302-cases.rst ├── 0313-countdown-benchmark.png ├── 0313-delimited-continuation-primops.rst ├── 0314-warn-noncanonical-monad-instance-by-default.rst ├── 0320-signature-instances.rst ├── 0344-negative-literals-improved.rst ├── 0364-unify-natural.rst ├── 0366-no-ambiguous-field-access.rst ├── 0369-sum-to-tag.rst ├── 0370-modifiers.rst ├── 0371-non-magical-eq.md ├── 0372-ghc-extensions.rst ├── 0378-dependent-type-design.rst ├── 0380-ghc2021.rst ├── 0387-char-kind.rst ├── 0402-gadt-syntax.rst ├── 0403-cleanup-lexical-structure.rst ├── 0409-exportable-named-default.rst ├── 0415-opaque-pragma.rst ├── 0425-decl-invis-binders.rst ├── 0433-unsatisfiable.rst ├── 0451-sized-literals.rst ├── 0475-tuple-syntax.rst ├── 0477-unicode-ellipsis.rst ├── 0496-empty-record-wildcards.rst └── 0511-deep-subsumption.rst ├── rich-diff.png ├── shell.nix └── venv.sh /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _venv 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: nix 2 | script: nix-shell shell.nix --run "make html" 3 | 4 | -------------------------------------------------------------------------------- /GRC.rst: -------------------------------------------------------------------------------- 1 | Haskell committee guidelines for respectful communication 2 | ========================================================= 3 | 4 | Preamble 5 | -------- 6 | 7 | The GHC Steering Committee has adopted these guidelines for respectful 8 | communication. 9 | 10 | We do not seek to impose these guidelines on members of the Haskell community 11 | generally. Rather it is a signal that we seek high standards of discourse in 12 | the Haskell community, and are willing to publicly hold ourselves to that 13 | standard, in the hope that others may voluntarily follow suit. 14 | 15 | Motivation 16 | ---------- 17 | 18 | We are motivated to adopt a set of guidelines for respectful communication for 19 | several reasons 20 | 21 | * Diversity and inclusion. We recognize that the Haskell community, echoing 22 | the technology industry more generally, skews white and male. We see it as our 23 | duty and honour to spread the joy of Haskell widely and to broaden the patterns 24 | of participation, in the hopes that, one day, we will no longer be askew. 25 | 26 | * Making an explicit commitment will encourage us to review our messages to see 27 | if they meet the goals set out here, and will give others some specifics to 28 | point to if we fail. 29 | 30 | Guidelines for respectful communication 31 | --------------------------------------- 32 | 33 | As members of a Haskell committee, we commit ourselves to a high standard of 34 | public behaviour. We have one over-arching rule: 35 | 36 | **We strive to treat every person with respect.** 37 | 38 | Specifically, we aspire to these qualities: 39 | 40 | * We treat everyone with courtesy, aware that their diverse backgrounds, 41 | experiences, goals, and perspectives may be very different to ours. 42 | 43 | * In our communication, we consistently honour and affirm the passion, 44 | professional expertise, and good intentions of others. Even if we 45 | occasionally doubt these qualities in someone else, we will not make public 46 | accusations of incompetence, malice or ulterior motives. 47 | 48 | * We strive to be scrupulously polite at all times. There should be no 49 | rudeness, name-calling, or harassment in our communication. 50 | 51 | * Where we disagree with someone, we avoid forms of expression that might make 52 | our dialogue partner feel attacked, humiliated, demeaned, or marginalised. 53 | Our critique should always be of specific statements and claims, never of 54 | people. 55 | 56 | * Disagreement itself is fine: we are enriched by robust technical debate. But 57 | we seek to make the tone of that debate to be a conversation among people who 58 | respect, or even admire, each other. 59 | 60 | * Where we disagree, we try to be curious about the perspective, goals, 61 | motivation, and priorities of the other person. 62 | 63 | * We do not tolerate any form of discriminatory language or behaviour towards 64 | any minority (for example age, body size, disability, ethnicity, sex 65 | characteristics, gender identity and expression, level of experience, 66 | education, socio-economic status, nationality, personal appearance, race, 67 | religion, or sexual identity and orientation). 68 | 69 | We seek to apply these standards in all our public interactions in the Haskell 70 | sphere, including email, social media, discussion forums, and so on. 71 | 72 | If one of us fails to meet these standards, the ideal course of action is to 73 | write to that person privately, gently drawing attention to their lapse. If 74 | you're not comfortable with that, please contact the chair of the committee, or 75 | (if the chair is the problem) the vice-chair or co-chair. 76 | 77 | Our response should usually be to apologise and stop doing what it was that you 78 | are unhappy about. Even if we feel we have been misinterpreted or unfairly 79 | accused, the chances are good there was something we could have communicated 80 | better, and an apology is far more likely to bring healing than is a 81 | counter-accusation. 82 | 83 | Acknowledgements 84 | ---------------- 85 | 86 | We'd like to thank the communities and projects that established code of 87 | conducts and diversity statements as our inspiration, including these: 88 | 89 | * A month before this document was first published, Michael Snoyman proposed 90 | a `Stack code of conduct 91 | `_ with a 92 | motivation similar to ours. 93 | * The `GNU Kind Communication Guidelines 94 | `_, published in 95 | October 2018, also express the positive tone we seek; `Stallman’s post 96 | `_ explains the intent. 97 | * The `Snowdrift community code of conduct `_ also has a companion `Guidelines for healthy communication `_. 98 | * `Open code of conduct `_ 99 | * `Pycon code of conduct `_ 100 | * `Rust code of conduct `_ 101 | * `TypeLevel code of conduct `_ 102 | * `Contributor covenant `_ 103 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = ghc-proposals 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /acceptance.rst: -------------------------------------------------------------------------------- 1 | How to Accept a Proposal 2 | ======================== 3 | 4 | This document describes the technical process for accepting a proposal, 5 | assuming the proposal has gone through the `proposal process `_. 6 | 7 | Acceptance checklist 8 | -------------------- 9 | 10 | Before accepting, the shepherd should check for the following 11 | (extracted from the `review criteria `_): 12 | 13 | 1. Is the proposal self-standing? It should not refer explicitly to the GitHub 14 | trail, for instance. 15 | 16 | 2. Is the proposal precise? The specification section should fully describe 17 | the proposal payload. In particular: 18 | 19 | a. If there is new syntax, is it described in BNF notation? 20 | 21 | b. If applicable, are there typing rules? If there are not, could 22 | typing rules be reasonably extracted from the proposal text? 23 | 24 | c. Are any changes to runtime behavior precisely specified? 25 | 26 | d. Is there a reasonable description of how the new feature might 27 | be documented in Haddock? Linted by HLint? Treated by other tools? 28 | (These will not apply to every proposal.) 29 | 30 | 3. Is the proposal sufficiently illustrated with examples? Examples help 31 | us understand the details that will be needed during implementation. 32 | 33 | Acceptance steps 34 | ---------------- 35 | 36 | A committee member accepts a proposal by following this sequence of 37 | steps: 38 | 39 | 1. Add a new commit on top of the PR branch that: 40 | 41 | a. Changes the filename of the proposal to correspond to the PR number. 42 | 43 | b. Updates any metadata fields that may have changed in the template on ``master`` since 44 | the PR branch split off. 45 | 46 | c. Fills in these metadata fields as appropriate, including changing "is discussed" 47 | to "was discussed". 48 | 49 | 2. Merge the PR branch into master, and push. 50 | 51 | 3. Update the PR description to start 52 | with the text "The proposal has been accepted; the following discussion is mostly of historic interest." 53 | where the word "proposal" links to the final rendered version, as found on https://github.com/ghc-proposals/ghc-proposals/tree/master/proposals 54 | 55 | 4. If the PR title has "(under review)", remove it. 56 | 57 | 5. Set the PR to have the "Accepted" label. 58 | 59 | 6. Comment on the PR that the proposal was accepted. 60 | 61 | 7. Close the PR if GitHub has not detected the merge. 62 | 63 | 8. Announce on the committee mailing list. 64 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'ghc-proposals' 23 | copyright = u'2019, The GHC Steering Committee' 24 | author = u'The GHC Steering Committee' 25 | 26 | # The short X.Y version 27 | version = u'' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | ] 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ['_templates'] 46 | 47 | # The suffix(es) of source filenames. 48 | # You can specify multiple suffix as a list of string: 49 | # 50 | # source_suffix = ['.rst', '.md'] 51 | source_suffix = '.rst' 52 | 53 | # The master toctree document. 54 | master_doc = 'index' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | # 59 | # This is also used if you do content translation via gettext catalogs. 60 | # Usually you set "language" from the command line for these cases. 61 | language = None 62 | 63 | # List of patterns, relative to source directory, that match files and 64 | # directories to ignore when looking for source files. 65 | # This pattern also affects html_static_path and html_extra_path . 66 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', "proposals/0000-template.rst"] 67 | 68 | # The name of the Pygments (syntax highlighting) style to use. 69 | pygments_style = 'sphinx' 70 | 71 | 72 | # -- Options for HTML output ------------------------------------------------- 73 | 74 | # The theme to use for HTML and HTML Help pages. See the documentation for 75 | # a list of builtin themes. 76 | # 77 | html_theme = 'haiku' 78 | 79 | # Theme options are theme-specific and customize the look and feel of a theme 80 | # further. For a list of options available for each theme, see the 81 | # documentation. 82 | # 83 | # html_theme_options = {} 84 | 85 | # Add any paths that contain custom static files (such as style sheets) here, 86 | # relative to this directory. They are copied after the builtin static files, 87 | # so a file named "default.css" will overwrite the builtin "default.css". 88 | html_static_path = ['_static'] 89 | 90 | # Custom sidebar templates, must be a dictionary that maps document names 91 | # to template names. 92 | # 93 | # The default sidebars (for documents that don't match any pattern) are 94 | # defined by theme itself. Builtin themes are using these templates by 95 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 96 | # 'searchbox.html']``. 97 | # 98 | # html_sidebars = {} 99 | 100 | 101 | # -- Options for HTMLHelp output --------------------------------------------- 102 | 103 | # Output file base name for HTML help builder. 104 | htmlhelp_basename = 'ghc-proposalsdoc' 105 | 106 | 107 | # -- Options for LaTeX output ------------------------------------------------ 108 | 109 | latex_elements = { 110 | # The paper size ('letterpaper' or 'a4paper'). 111 | # 112 | # 'papersize': 'letterpaper', 113 | 114 | # The font size ('10pt', '11pt' or '12pt'). 115 | # 116 | # 'pointsize': '10pt', 117 | 118 | # Additional stuff for the LaTeX preamble. 119 | # 120 | # 'preamble': '', 121 | 122 | # Latex figure (float) alignment 123 | # 124 | # 'figure_align': 'htbp', 125 | } 126 | 127 | # Grouping the document tree into LaTeX files. List of tuples 128 | # (source start file, target name, title, 129 | # author, documentclass [howto, manual, or own class]). 130 | latex_documents = [ 131 | (master_doc, 'ghc-proposals.tex', u'GHC Proposals', 132 | u'GHC', 'manual'), 133 | ] 134 | 135 | 136 | # -- Options for manual page output ------------------------------------------ 137 | 138 | # One entry per manual page. List of tuples 139 | # (source start file, name, description, authors, manual section). 140 | man_pages = [ 141 | (master_doc, 'ghc-proposals', u'GHC Proposals', 142 | [author], 1) 143 | ] 144 | 145 | 146 | # -- Options for Texinfo output ---------------------------------------------- 147 | 148 | # Grouping the document tree into Texinfo files. List of tuples 149 | # (source start file, target name, title, author, 150 | # dir menu entry, description, category) 151 | texinfo_documents = [ 152 | (master_doc, 'ghc-proposals', u'GHC Proposals', 153 | author, 'ghc-proposals', 'One line description of project.', 154 | 'Miscellaneous'), 155 | ] 156 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | All accepted GHC Proposals 2 | ========================== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | :glob: 8 | 9 | README.rst 10 | GRC.rst 11 | proposals/* 12 | 13 | 14 | Indices and tables 15 | ================== 16 | 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | -------------------------------------------------------------------------------- /inline-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tweag/ghc-proposals/cff853ec8c756d8c81abf69427036963edbafd4e/inline-comment.png -------------------------------------------------------------------------------- /principles.rst: -------------------------------------------------------------------------------- 1 | .. sectnum:: 2 | .. highlight:: haskell 3 | 4 | Principles for GHC 5 | ================== 6 | 7 | This document lays out high-level principles for the evolution of GHC 8 | and the language it compiles. In much the way that we like to write 9 | *properties* of our functions -- instead of just writing down individual 10 | test cases -- this document strives to write *principles* that our proposals 11 | ought to maintain (or build towards). 12 | 13 | Articulating these principles helps to guide future proposals: proposals 14 | that maintain the principles in this document are more likely to be accepted, 15 | while proposals that work against these principles are more likely to be rejected. 16 | Note that neither direction is (at all) a guarantee: there will be excpetions 17 | in both directions. Yet by writing down the principles, we can have an informed 18 | discussion of the tradeoffs of accepted or rejecting an individual proposal. 19 | 20 | How to update these principles 21 | ------------------------------ 22 | 23 | When making a proposal, following the `usual guidelines `_, 24 | feel free to include a diff against this listing of principles. We can then 25 | discuss the validity of the new principle(s) alongside the concrete proposal for 26 | a change to GHC. 27 | 28 | We urge proposers to resist the temptation to propose principles without an 29 | accompanying concrete change to GHC. Debating principles in the abstract does 30 | not seem a productive use of time, though it is possible to imagine exceptions. 31 | For example, the justification for the rejection of a proposal may be distilled into 32 | a new principle here. Accordingly, this document is not (and presumably never will be) 33 | comprehensive: it contains the articulated prinicples guiding GHC's development 34 | but lacks the unarticulated principles, which will be added over time. 35 | 36 | All principles in this document are linked back to the PR that introduce them, 37 | so that readers can learn the context in which they were written. 38 | 39 | Accepted principles 40 | ------------------- 41 | 42 | .. _`#378`: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0378-dependent-type-design.rst 43 | 44 | Syntax 45 | ~~~~~~ 46 | 47 | .. _SUP: 48 | 49 | **Syntactic Unification Principle (SUP).** (From `#378`_.) In the absence of punning, there is 50 | no difference between type-syntax and term-syntax. 51 | 52 | The SUP_ is a *long term* goal; today, there are many, many violations of this principle. (For example, 53 | ``case`` can never appear in types, and ``Int -> Bool`` is meaningless in a term.) However, this principle 54 | should direct future proposals not to make the situation worse, and proposals that bring us closer to 55 | the SUP_ are to be valued. 56 | 57 | Name resolution 58 | ~~~~~~~~~~~~~~~ 59 | 60 | .. _LSP: 61 | 62 | **Lexical Scoping Principle (LSP)**. (From `#378`_.) For every *occurrence* of an 63 | identifier, it is possible to uniquely identify its *binding site*, without 64 | involving the type system. 65 | 66 | The LSP_ is true today, though Template Haskell splices may need to be run before 67 | completing name resolution (and running those splices requires type-checking them). 68 | 69 | Semantics 70 | ~~~~~~~~~ 71 | 72 | .. _PEP: 73 | 74 | **Predictable Erasure Principle (PEP)**. (From `#378`_.) The programmer knows, for sure, which bits of the program will be 75 | retained at runtime, and which will be erased. 76 | 77 | The PEP_ is true today: types are erased, while terms are retained. 78 | 79 | User experience 80 | ~~~~~~~~~~~~~~~ 81 | 82 | .. _OIP: 83 | 84 | **The Opt-In Principle (OIP):** (From `#378`_, slightly generalized.) Users who do not opt into an advanced feature will 85 | not be affected by it. 86 | 87 | This principle is violated in various ways today: it is easy for GHC to generate error messages that refer to 88 | advanced features even when writing simple code. In addition, the existence of advanced features likely slow 89 | down GHC even when those features are not active. Yet this principle is important to keep in mind going forward, 90 | as we hope not to make the current situation worse. -------------------------------------------------------------------------------- /proposals/0000-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Your name 3 | date-accepted: "" 4 | ticket-url: "" 5 | implemented: "" 6 | --- 7 | 8 | This proposal is [discussed at this pull request](https://github.com/ghc-proposals/ghc-proposals/pull/0>). 9 | **After creating the pull request, edit this file again, update the number in 10 | the link, and delete this bold sentence.** 11 | 12 | # Proposal title 13 | 14 | Here you should write a short abstract motivating and briefly summarizing the 15 | proposed change. 16 | 17 | 18 | ## Motivation 19 | 20 | Give a strong reason for why the community needs this change. Describe the use 21 | case as clearly as possible and give an example. Explain how the status quo is 22 | insufficient or not ideal. 23 | 24 | A good Motivation section is often driven by examples and real-world scenarios. 25 | 26 | 27 | ## Proposed Change Specification 28 | 29 | Specify the change in precise, comprehensive yet concise language. Avoid words 30 | like "should" or "could". Strive for a complete definition. Your specification 31 | may include, 32 | 33 | * BNF grammar and semantics of any new syntactic constructs 34 | (Use the [Haskell 2010 Report](https://www.haskell.org/onlinereport/haskell2010/) or GHC's 35 | `alex`- or `happy`-formatted files 36 | for the [lexer](https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Parser/Lexer.x) or [parser](https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Parser.y) 37 | for a good starting point.) 38 | * the types and semantics of any new library interfaces 39 | * how the proposed change interacts with existing language or compiler 40 | features, in case that is otherwise ambiguous 41 | 42 | Strive for *precision*. The ideal specification is described as a 43 | modification of the [Haskell 2010 44 | report](https://www.haskell.org/definition/haskell2010.pdf). Where 45 | that is not possible (e.g. because the specification relates to a 46 | feature that is not in the Haskell 2010 report), try to adhere its 47 | style and level of detail. Think about corner cases. Write down 48 | general rules and invariants. 49 | 50 | Note, however, that this section should focus on a precise 51 | *specification*; it need not (and should not) devote space to 52 | *implementation* details -- there is a separate section for that. 53 | 54 | The specification can, and almost always should, be illustrated with 55 | *examples* that illustrate corner cases. But it is not sufficient to 56 | give a couple of examples and regard that as the specification! The 57 | examples should illustrate and elucidate a clearly-articulated 58 | specification that covers the general case. 59 | 60 | ## Examples 61 | 62 | This section illustrates the specification through the use of examples of the 63 | language change proposed. It is best to exemplify each point made in the 64 | specification, though perhaps one example can cover several points. Contrived 65 | examples are OK here. If the Motivation section describes something that is 66 | hard to do without this proposal, this is a good place to show how easy that 67 | thing is to do with the proposal. 68 | 69 | ## Effect and Interactions 70 | 71 | Your proposed change addresses the issues raised in the 72 | motivation. Explain how. 73 | 74 | Also, discuss possibly contentious interactions with existing language or compiler 75 | features. Complete this section with potential interactions raised 76 | during the PR discussion. 77 | 78 | 79 | ## Costs and Drawbacks 80 | 81 | Give an estimate on development and maintenance costs. List how this effects 82 | learnability of the language for novice users. Define and list any remaining 83 | drawbacks that cannot be resolved. 84 | 85 | 86 | ## Alternatives 87 | 88 | List alternative designs to your proposed change. Both existing 89 | workarounds, or alternative choices for the changes. Explain 90 | the reasons for choosing the proposed change over these alternative: 91 | *e.g.* they can be cheaper but insufficient, or better but too 92 | expensive. Or something else. 93 | 94 | The PR discussion often raises other potential designs, and they should be 95 | added to this section. Similarly, if the proposed change 96 | specification changes significantly, the old one should be listed in 97 | this section. 98 | 99 | ## Unresolved Questions 100 | 101 | Explicitly list any remaining issues that remain in the conceptual design and 102 | specification. Be upfront and trust that the community will help. Please do 103 | not list *implementation* issues. 104 | 105 | Hopefully this section will be empty by the time the proposal is brought to 106 | the steering committee. 107 | 108 | 109 | ## Implementation Plan 110 | 111 | (Optional) If accepted who will implement the change? Which other resources 112 | and prerequisites are required for implementation? 113 | 114 | ## Endorsements 115 | 116 | (Optional) This section provides an opportunity for any third parties to express their 117 | support for the proposal, and to say why they would like to see it adopted. 118 | It is not mandatory for have any endorsements at all, but the more substantial 119 | the proposal is, the more desirable it is to offer evidence that there is 120 | significant demand from the community. This section is one way to provide 121 | such evidence. 122 | 123 | -------------------------------------------------------------------------------- /proposals/0000-template.rst: -------------------------------------------------------------------------------- 1 | Notes on reStructuredText - delete this section before submitting 2 | ================================================================== 3 | 4 | The proposals are submitted in reStructuredText format. To get inline code, enclose text in double backticks, ``like this``. To get block code, use a double colon and indent by at least one space 5 | 6 | :: 7 | 8 | like this 9 | and 10 | 11 | this too 12 | 13 | To get hyperlinks, use backticks, angle brackets, and an underscore `like this `_. 14 | 15 | 16 | Proposal title 17 | ============== 18 | 19 | .. author:: Your name 20 | .. date-accepted:: Leave blank. This will be filled in when the proposal is accepted. 21 | .. ticket-url:: Leave blank. This will eventually be filled with the 22 | ticket URL which will track the progress of the 23 | implementation of the feature. 24 | .. implemented:: Leave blank. This will be filled in with the first GHC version which 25 | implements the described feature. 26 | .. highlight:: haskell 27 | .. header:: This proposal is `discussed at this pull request `_. 28 | **After creating the pull request, edit this file again, update the 29 | number in the link, and delete this bold sentence.** 30 | .. sectnum:: 31 | .. contents:: 32 | 33 | Here you should write a short abstract motivating and briefly summarizing the proposed change. 34 | 35 | 36 | Motivation 37 | ---------- 38 | Give a strong reason for why the community needs this change. Describe the use 39 | case as clearly as possible and give an example. Explain how the status quo is 40 | insufficient or not ideal. 41 | 42 | A good Motivation section is often driven by examples and real-world scenarios. 43 | 44 | 45 | Proposed Change Specification 46 | ----------------------------- 47 | Specify the change in precise, comprehensive yet concise language. Avoid words 48 | like "should" or "could". Strive for a complete definition. Your specification 49 | may include, 50 | 51 | * BNF grammar and semantics of any new syntactic constructs 52 | (Use the `Haskell 2010 Report `_ or GHC's ``alex``\- or ``happy``\-formatted files 53 | for the `lexer `_ or `parser `_ 54 | for a good starting point.) 55 | * the types and semantics of any new library interfaces 56 | * how the proposed change interacts with existing language or compiler 57 | features, in case that is otherwise ambiguous 58 | 59 | Strive for *precision*. The ideal specification is described as a 60 | modification of the `Haskell 2010 report 61 | `_. Where that is 62 | not possible (e.g. because the specification relates to a feature that 63 | is not in the Haskell 2010 report), try to adhere its style and level 64 | of detail. Think about corner cases. Write down general rules and 65 | invariants. 66 | 67 | Note, however, that this section should focus on a precise 68 | *specification*; it need not (and should not) devote space to 69 | *implementation* details -- there is a separate section for that. 70 | 71 | The specification can, and almost always should, be illustrated with 72 | *examples* that illustrate corner cases. But it is not sufficient to 73 | give a couple of examples and regard that as the specification! The 74 | examples should illustrate and elucidate a clearly-articulated 75 | specification that covers the general case. 76 | 77 | Examples 78 | -------- 79 | This section illustrates the specification through the use of examples of the 80 | language change proposed. It is best to exemplify each point made in the 81 | specification, though perhaps one example can cover several points. Contrived 82 | examples are OK here. If the Motivation section describes something that is 83 | hard to do without this proposal, this is a good place to show how easy that 84 | thing is to do with the proposal. 85 | 86 | Effect and Interactions 87 | ----------------------- 88 | Your proposed change addresses the issues raised in the motivation. Explain how. 89 | 90 | Also, discuss possibly contentious interactions with existing language or compiler 91 | features. Complete this section with potential interactions raised 92 | during the PR discussion. 93 | 94 | 95 | Costs and Drawbacks 96 | ------------------- 97 | Give an estimate on development and maintenance costs. List how this effects 98 | learnability of the language for novice users. Define and list any remaining 99 | drawbacks that cannot be resolved. 100 | 101 | 102 | Alternatives 103 | ------------ 104 | List alternative designs to your proposed change. Both existing 105 | workarounds, or alternative choices for the changes. Explain 106 | the reasons for choosing the proposed change over these alternative: 107 | *e.g.* they can be cheaper but insufficient, or better but too 108 | expensive. Or something else. 109 | 110 | The PR discussion often raises other potential designs, and they should be 111 | added to this section. Similarly, if the proposed change 112 | specification changes significantly, the old one should be listed in 113 | this section. 114 | 115 | Unresolved Questions 116 | -------------------- 117 | Explicitly list any remaining issues that remain in the conceptual design and 118 | specification. Be upfront and trust that the community will help. Please do 119 | not list *implementation* issues. 120 | 121 | Hopefully this section will be empty by the time the proposal is brought to 122 | the steering committee. 123 | 124 | 125 | Implementation Plan 126 | ------------------- 127 | (Optional) If accepted who will implement the change? Which other resources 128 | and prerequisites are required for implementation? 129 | 130 | Endorsements 131 | ------------- 132 | (Optional) This section provides an opportunity for any third parties to express their 133 | support for the proposal, and to say why they would like to see it adopted. 134 | It is not mandatory for have any endorsements at all, but the more substantial 135 | the proposal is, the more desirable it is to offer evidence that there is 136 | significant demand from the community. This section is one way to provide 137 | such evidence. 138 | -------------------------------------------------------------------------------- /proposals/0002-overloaded-record-fields.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0023-overloaded-record-fields.rst 2 | -------------------------------------------------------------------------------- /proposals/0003-levity-polymorphism.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0029-levity-polymorphism.rst 2 | -------------------------------------------------------------------------------- /proposals/0004-hexFloats.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0037-hexFloats.rst 2 | -------------------------------------------------------------------------------- /proposals/0005-bidir-constr-sigs.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0042-bidir-constr-sigs.rst 2 | -------------------------------------------------------------------------------- /proposals/0006-deriving-empty.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0063-deriving-empty.rst 2 | -------------------------------------------------------------------------------- /proposals/0007-instance-foralls.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0055-instance-foralls.rst 2 | -------------------------------------------------------------------------------- /proposals/0008-type-infix.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0065-type-infix.rst 2 | -------------------------------------------------------------------------------- /proposals/0009-numeric-underscores.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0076-numeric-underscores.rst 2 | -------------------------------------------------------------------------------- /proposals/0010-block-arguments.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0090-block-arguments.rst 2 | -------------------------------------------------------------------------------- /proposals/0011-deprecate-stm-invariants.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0077-deprecate-stm-invariants.rst 2 | -------------------------------------------------------------------------------- /proposals/0012-Wall-uni-patterns.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0071-Wall-uni-patterns.rst 2 | -------------------------------------------------------------------------------- /proposals/0013-unlifted-newtypes.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0098-unlifted-newtypes.rst 2 | -------------------------------------------------------------------------------- /proposals/0014-small-primitives.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0074-small-primitives.rst 2 | -------------------------------------------------------------------------------- /proposals/0015-type-level-type-applications.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0080-type-level-type-applications.rst 2 | -------------------------------------------------------------------------------- /proposals/0016-as-patterns-synonyms.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0094-as-patterns-synonyms.rst 2 | -------------------------------------------------------------------------------- /proposals/0017-source-plugins.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0107-source-plugins.rst 2 | -------------------------------------------------------------------------------- /proposals/0018-quantified-constraints.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0109-quantified-constraints.rst 2 | -------------------------------------------------------------------------------- /proposals/0019-constraint-vs-type.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0032-constraint-vs-type.rst 2 | -------------------------------------------------------------------------------- /proposals/0020-no-type-in-type.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0083-no-type-in-type.rst 2 | -------------------------------------------------------------------------------- /proposals/0021-unlifted-array.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0112-unlifted-array.rst 2 | -------------------------------------------------------------------------------- /proposals/0022-plugin-recompilation.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0108-plugin-recompilation.rst 2 | -------------------------------------------------------------------------------- /proposals/0023-deriving-via.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0120-deriving-via.rst 2 | -------------------------------------------------------------------------------- /proposals/0024-no-kind-vars.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0103-no-kind-vars.rst 2 | -------------------------------------------------------------------------------- /proposals/0025-resize-boxed.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0121-resize-boxed.rst 2 | -------------------------------------------------------------------------------- /proposals/0026-explicit-specificity.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0099-explicit-specificity.rst 2 | -------------------------------------------------------------------------------- /proposals/0027-atomicModifyMutVar.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0149-atomicModifyMutVar.rst 2 | -------------------------------------------------------------------------------- /proposals/0028-deprecating-exports-proposal.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0134-deprecating-exports-proposal.rst 2 | -------------------------------------------------------------------------------- /proposals/0029-levity-polymorphism.rst: -------------------------------------------------------------------------------- 1 | Revise Levity Polymorphism 2 | ========================== 3 | 4 | .. author:: Richard Eisenberg 5 | .. date-accepted:: 2017-02-04 6 | .. ticket-url:: https://phabricator.haskell.org/D2842 7 | .. implemented:: 8.2.1 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | GHC 8 introduced *levity polymorphism*, where a variable can be polymorphic in 13 | its representation. (This is also known as "representation polymorphism", but 14 | levity polymorphism surely has a better ring to it. This proposal also 15 | solidifies this name for the feature.) However, levity polymorphism still has 16 | some rough edges; this proposal smoothes them out by parameterizing 17 | ``UnboxedTupleRep`` and ``UnboxedSumRep``. This proposal also renames some 18 | definitions to make them shorter. 19 | 20 | Motivation 21 | ---------- 22 | 23 | This is useful in the types of ``undefined`` and ``error`` as well as in 24 | simplifying type inference a good deal, with the abolishment of sub-kinding. 25 | 26 | As @Iceland_jack has pointed out, levity polymorphism also allows us to 27 | overload operations like ``+`` over unlifted types. (See `this bug report`_.) 28 | 29 | .. _this bug report: https://gitlab.haskell.org/ghc/ghc/issues/12708 30 | 31 | Further motivation is available in Simon and my `paper on the subject`_. 32 | 33 | .. _paper on the subject: http://cs.brynmawr.edu/~rae/papers/2017/levity/levity.pdf 34 | 35 | Motivating this change is the fact that unboxed tuples and sums don't really 36 | work. For example, GHC accepts this nonsense:: 37 | 38 | type family F a where 39 | F Int = (# Int, Bool #) 40 | F Bool = (# Int# #) 41 | 42 | It's nonsense because the two return types actually have different 43 | representations! With the changes proposed here, such a type family would be 44 | safe. 45 | 46 | Proposed Change 47 | --------------- 48 | 49 | Here is the current state of affairs:: 50 | 51 | TYPE :: RuntimeRep -> Type -- super-magical constant 52 | data RuntimeRep = PtrRepLifted 53 | | PtrRepUnlifted 54 | | VoidRep 55 | | IntRep 56 | | FloatRep 57 | | ... 58 | | UnboxedTupleRep 59 | | UnboxedSumRep 60 | type Type = TYPE PtrRepLifted 61 | 62 | With these definitions, all "normal" types have type ``TYPE PtrRepLifted`` 63 | (that is, ``Type``). Unboxed types are kinded similarly, with 64 | ``Int# :: TYPE IntRep`` and ``Array# :: Type -> TYPE PtrRepUnlifted``. 65 | 66 | The problem is that all unboxed tuples have the same kind, 67 | ``TYPE UnboxedTupleRep``. 68 | This violates the intent of levity polymorphism, wherein 69 | the kind of a type tells you its representation (and calling convention). 70 | 71 | I propose changing this to become:: 72 | 73 | TYPE :: RuntimeRep -> Type -- same super-magical constant 74 | data RuntimeRep = LiftedRep 75 | | UnliftedRep 76 | | IntRep 77 | | FloatRep 78 | | ... 79 | | TupleRep [RuntimeRep] 80 | | SumRep [RuntimeRep] 81 | type Type = TYPE LiftedRep 82 | 83 | Note the name changes and the new parameters to ``TupleRep`` and ``SumRep``. 84 | These parameters mean that different unboxed tuples/sums have *different* 85 | kinds. Hooray! 86 | 87 | Also, this change removes ``VoidRep`` in favor of ``TupleRep []``, a small 88 | simplification. 89 | 90 | Drawbacks 91 | --------- 92 | 93 | The renaming is indeed gratuitous. But it still seems early enough in the 94 | adoption of this feature that we can do this. Note that the changed names are 95 | exported only by ``GHC.Types`` and ``GHC.Exts``, so programs using these names 96 | have opted into experimental features. 97 | 98 | Alternatives 99 | ------------ 100 | 101 | I argue that the status quo is untenable, because it fails to fulfill the 102 | promise of levity polymorphism. 103 | 104 | One alternative is presented in Simon and my `paper on the subject`_, where 105 | ``TYPE :: [RuntimeRep] -> Type`` (note the list!). The list contains the 106 | representations of all components of an unboxed tuple. Anything other than an 107 | unboxed tuple has a singleton list. This alternative is more elaborate than 108 | what is proposed here, and it would allow, for example :: 109 | 110 | foo :: forall (a :: TYPE '[IntRep, FloatRep]). a -> a 111 | foo x = x 112 | 113 | to be instantiated, say, at both ``(# Int#, Float# #)`` and 114 | ``(# Int#, (# (# #), Float# #) #)``, 115 | because these both have the same representation. This is 116 | all well and type-safe, but no one is really asking for this feature, and it 117 | complicates the type system. 118 | 119 | A fully broken partial implementation of this is available `here`__. 120 | 121 | __ https://github.com/goldfirere/ghc/tree/wip/runtime-rep-lists 122 | 123 | Unresolved Questions 124 | -------------------- 125 | 126 | I don't have any at the moment. 127 | 128 | Related Concerns 129 | ---------------- 130 | 131 | The original introduction of levity polymorphism generated much consternation 132 | around, e.g., the type of ``($)``, which suddenly became quite complicated. 133 | (To wit: 134 | ``($) :: forall (r :: RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b``) 135 | This was fixed by adding a new flag to GHC, 136 | ``-fprint-explicit-runtime-reps``, without which the levity polymorphic bits 137 | get defaulted to `PtrRepLifted`, making everything look non-scary again. This 138 | proposal makes *no* change to this behavior. 139 | -------------------------------------------------------------------------------- /proposals/0029-scoped-type-variables-types.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0128-scoped-type-variables-types.rst 2 | -------------------------------------------------------------------------------- /proposals/0030-remove-star-kind.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0143-remove-star-kind.rst 2 | -------------------------------------------------------------------------------- /proposals/0031-type-applications-in-patterns.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0126-type-applications-in-patterns.rst 2 | -------------------------------------------------------------------------------- /proposals/0032-type-data.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0106-type-data.rst 2 | -------------------------------------------------------------------------------- /proposals/0033-unbanged-strict-patterns.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0035-unbanged-strict-patterns.rst 2 | -------------------------------------------------------------------------------- /proposals/0034-stable-names.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0163-stable-names.rst 2 | -------------------------------------------------------------------------------- /proposals/0035-forall-arrow.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst 2 | -------------------------------------------------------------------------------- /proposals/0036-kind-signatures.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0054-kind-signatures.rst 2 | -------------------------------------------------------------------------------- /proposals/0037-unpack-pragma-precedence.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0174-unpack-pragma-precedence.rst 2 | -------------------------------------------------------------------------------- /proposals/0038-fail-rebindable-with-overloaded-strings.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0168-fail-rebindable-with-overloaded-strings.rst 2 | -------------------------------------------------------------------------------- /proposals/0039-dot-type-operator.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0173-dot-type-operator.rst 2 | -------------------------------------------------------------------------------- /proposals/0040-unrestricted-overloadedlabels.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0170-unrestricted-overloadedlabels.rst 2 | -------------------------------------------------------------------------------- /proposals/0041-ghci-instances.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0166-ghci-instances.rst 2 | -------------------------------------------------------------------------------- /proposals/0042-record-set-field.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0158-record-set-field.rst 2 | -------------------------------------------------------------------------------- /proposals/0043-forall-keyword.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0193-forall-keyword.rst 2 | -------------------------------------------------------------------------------- /proposals/0044-minimal-should-warn-extras.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0210-minimal-should-warn-extras.rst 2 | -------------------------------------------------------------------------------- /proposals/0045-pointer-rep.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0203-pointer-rep.rst 2 | -------------------------------------------------------------------------------- /proposals/0046-scc-parsing.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0176-scc-parsing.rst 2 | -------------------------------------------------------------------------------- /proposals/0047-levity-polymorphic-lift.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0209-levity-polymorphic-lift.rst 2 | -------------------------------------------------------------------------------- /proposals/0048-printing-foralls.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0179-printing-foralls.rst 2 | -------------------------------------------------------------------------------- /proposals/0049-module-qualified-syntax.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0190-module-qualified-syntax.rst 2 | -------------------------------------------------------------------------------- /proposals/0050-type-lambda.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0155-type-lambda.rst 2 | -------------------------------------------------------------------------------- /proposals/0051-function-result-sigs.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0228-function-result-sigs.rst 2 | -------------------------------------------------------------------------------- /proposals/0052-threaded-by-default.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0240-threaded-by-default.rst 2 | -------------------------------------------------------------------------------- /proposals/0053-type-annotated-quoters.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0125-type-annotated-quoters.rst 2 | -------------------------------------------------------------------------------- /proposals/0054-AmbiguousType-pragma.rst: -------------------------------------------------------------------------------- 1 | This document was moved to https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0232-AmbiguousType-pragma.rst 2 | -------------------------------------------------------------------------------- /proposals/0071-Wall-uni-patterns.rst: -------------------------------------------------------------------------------- 1 | Extend ``-Wall`` with ``incomplete-uni-patterns`` and ``incomplete-record-updates`` 2 | ============== 3 | 4 | .. author:: tomjaguarpaw 5 | .. date-accepted:: 2018-02-07 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/15656 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | Extend ``-Wall`` with ``incomplete-uni-patterns`` and ``incomplete-record-updates`` 13 | because they warn only about things that should typically not occur in well-written 14 | modern Haskell. 15 | 16 | Motivation 17 | ------------ 18 | 19 | ``-Wall`` does not warn on the following, but ``-Wincomplete-uni-patterns`` does 20 | 21 | :: 22 | 23 | myHead :: [a] -> a 24 | myHead = \(a:as) -> a 25 | 26 | ``-Wall`` does not warn on the following, but ``-Wincomplete-record-updates`` does 27 | 28 | :: 29 | 30 | data Foo 31 | = Bar { barInt :: Int, barString :: String } 32 | | Baz 33 | 34 | mySetter :: Int -> Foo -> Foo 35 | mySetter int foo = foo { barInt = int } 36 | 37 | These code samples are in a style which is generally discouraged in modern Haskell 38 | and I suspect the vast majority of developers would want to be warned about these 39 | issues as standard. ``-Wall`` seems like a good standard place in which to apply 40 | them. 41 | 42 | Historically, ``incomplete-uni-patterns`` seems to have been kept out of ``-Wall`` 43 | by https://gitlab.haskell.org/ghc/ghc/issues/4905. It received no discussion nor 44 | counterpoints. Moreover, the change was made 6 years ago and standards for Haskell 45 | code in the wild have tightened somewhat since then. 46 | 47 | I made this suggestion `on Haskell Reddit 48 | `_ 49 | and it received net 48 upvotes with no dissenting responses. 50 | 51 | (Thanks to `Dennis Gosnell `_ 52 | for bringing this issue to my attention.) 53 | 54 | Proposed Change Specification 55 | ----------------------------- 56 | 57 | Extend the meaning of ``-Wall`` to include ``incomplete-uni-patterns`` and 58 | ``incomplete-record-updates``. 59 | 60 | Effect and Interactions 61 | ----------------------- 62 | 63 | Users using ``-Wall`` will be warned when they use ``incomplete-uni-patterns`` and 64 | ``incomplete-record-updates`` 65 | 66 | 67 | Costs and Drawbacks 68 | ------------------- 69 | 70 | Minimal development and maintenance costs. Existing code compiled with ``-Wall`` 71 | will start warning if it uses ``incomplete-uni-patterns`` or 72 | ``incomplete-record-updates`` 73 | 74 | Alternatives 75 | ------------ 76 | 77 | Specify ``incomplete-uni-patterns`` and ``incomplete-record-updates`` manually. 78 | 79 | Unresolved questions 80 | -------------------- 81 | 82 | None 83 | 84 | Implementation Plan 85 | ------------------- 86 | 87 | Minimal planning required. 88 | -------------------------------------------------------------------------------- /proposals/0074-small-primitives.rst: -------------------------------------------------------------------------------- 1 | 2 | Add more fixed size primitive types, like ``Int8#/Word8#`` 3 | ========================================================== 4 | 5 | .. author:: Michal Terepeta 6 | .. date-accepted:: 2018-03-01 7 | .. ticket-url:: https://phabricator.haskell.org/D5006, https://phabricator.haskell.org/D5258 8 | .. implemented:: GHC-8.10 9 | .. highlight:: haskell 10 | .. header:: This proposal was `discussed at this pull request `_. 11 | .. contents:: 12 | 13 | This proposes adding new primitive types to GHC: 14 | 15 | - ``Int8#``/``Word8#`` 16 | 17 | - ``Int16#``/``Word16#`` 18 | 19 | - ``Int32#``/``Word32#`` 20 | 21 | - ``Int64#``/``Word64#`` 22 | 23 | along with corresponding primitive operations. 24 | 25 | Motivation 26 | ------------ 27 | 28 | GHC currently only has a few machine-level primitives (not counting arrays or 29 | STM stuff): ``Int#``, ``Word#``, ``Float#``, ``Double#`` and ``Char#`` (which is 30 | a 31-bit character). This means that there is no way to express a value that is 31 | exactly one byte in size (or two, etc.), for instance, ``Word8`` is defined in 32 | terms of ``Word#`` (`definition of Word8`_) and thus will always take 64 bits 33 | (on 64-bit arch). This is not only wasteful in terms of space, but also 34 | counter-intuitive, consider: 35 | 36 | :: 37 | 38 | data MyStruct = 39 | MyStruct 40 | {-# UNPACK #-} !Word16 41 | {-# UNPACK #-} !Word16 42 | {-# UNPACK #-} !Word16 43 | {-# UNPACK #-} !Word16 44 | 45 | On 64-bit architecture one could expect that this takes just 8 bytes (in this 46 | proposal I'm ignoring the additional object header). However, GHC today will use 47 | 32 bytes for this (each field is a full 8-byte word). This can be quite 48 | surprising for people using C/C++, Rust, etc. For instance, in Rust the 49 | following structure would take only 8 bytes. 50 | 51 | :: 52 | 53 | struct MyStruct { 54 | a : u16, 55 | b : u16, 56 | c : u16, 57 | d : u16 58 | } 59 | 60 | The only way to achieve this in GHC would be to manually use an unboxed 61 | ``Word64`` and use shifts to extract the data, which is both less efficient and 62 | far more error-prone. 63 | 64 | .. _definition of Word8: https://github.com/ghc/ghc/blob/b3ae47caf2f23cfd2c22c29dbfca646493ffe469/libraries/base/GHC/Word.hs#L64 65 | 66 | Proposed Change Specification 67 | ----------------------------- 68 | 69 | Add and expose new primitive types: 70 | 71 | - ``Int8#``/``Word8#`` 72 | 73 | - ``Int16#``/``Word16#`` 74 | 75 | - ``Int32#``/``Word32#`` 76 | 77 | Along with the set of basic primitive operations (similar to ``Int#`` and 78 | ``Word#``) as well as conversions to/from ``Int#``/``Word#``. 79 | 80 | GHC could expose them along with ``Int#`` and ``Word#``. 81 | 82 | Effect and Interactions 83 | ----------------------- 84 | 85 | Having the new primitives in GHC would allow us to redefine types like 86 | ``Word{8,16,32}`` and ``Int{8,16,32}`` as well as cleanup 87 | ``Data.Int``/``Data.Word`` modules and get rid of ``narrow`` primitives (but 88 | note that this is not part of this proposal, I believe it should be a separate 89 | proposal to the libraries committee). 90 | 91 | There might be also interesting interactions with unpacked sums (note: 92 | ``UNPACK`` doesn't yet work on sum types yet). Consider: 93 | 94 | :: 95 | 96 | data MyStruct = 97 | MyStruct {#- UNPACK #-} !Bool 98 | {#- UNPACK #-} !Bool 99 | {#- UNPACK #-} !Bool 100 | {#- UNPACK #-} !Bool 101 | 102 | Without small primitive types, the only way to unpack this is to use at least 103 | one word per field (which on 64-bit arch this would correspond to a total of 4 * 104 | 8 = 32 bytes for the whole structure). If we had ``Word8#`` this could go down 105 | to a total of just one word (1 byte per ``Bool`` field, but rounded to a word 106 | due to heap layout). 107 | 108 | 109 | Costs and Drawbacks 110 | ------------------- 111 | 112 | Implementation shouldn't require any major changes/redesign and maintenance 113 | costs should be relatively small (nothing is likely to change after 114 | implementation). 115 | 116 | 117 | Alternatives 118 | ------------ 119 | 120 | The only alternative I can think of is to decide not to do this (but that not a 121 | very satisfactory "solution" to the problem ;) 122 | 123 | 124 | Unresolved questions 125 | -------------------- 126 | 127 | I don't see any, but please comment :) 128 | 129 | 130 | Implementation Plan 131 | ------------------- 132 | 133 | I would like to implement this (but might need some guidance :). 134 | 135 | I believe GHC's current calling convention would not have to change. For any 136 | parameters smaller than full register width, we will only use the bottom bits. 137 | From the implementation perspective, the caller might need to zero-extend the 138 | parameters and the callee to narrow them back. I believe this is what ``ghccc`` 139 | (`LLVM's calling convention for GHC`_) already does. 140 | 141 | An alternative would be to create a new calling convention to try to avoid the 142 | widening/narrowing, but so far all my attempts seemed overly complicated (due 143 | to, e.g., 32-bit x86 having the unfortunate limitation that not all registers 144 | have their lower 8-bits for use) 145 | 146 | Other than that, this proposal would require changing the following pieces of 147 | GHC (please comment if you know of any more places!): 148 | 149 | - Primops file (``compiler/prelude/primops.txt.pp``) 150 | 151 | - GHC's wired-in types to expose the new types (``compiler/prelude/TysPrim.hs``, 152 | ``compiler/prelude/TysWiredIn.hs``) 153 | 154 | - Extend ``TyCon.PrimRep`` (``compiler/types``) and `` ``GHC.Types.RuntimeRep`` 155 | (``ghc-prim``) to represent their width. We already have ``Int64``, so we 156 | could add a new constructor for each of the new primitives. Alternatively, we 157 | could have a single ``IntRep`` (``WordRep``) constructor parameterized by the 158 | width (similarly to what ``VecRep`` does). 159 | 160 | - Constant folding to support evaluating the new primitive operations 161 | (``compiler/prelude/PrelRules.hs``) 162 | 163 | - Codegen to support express the new operations as ``MachOp`` 164 | (``compiler/codeGen/StgCmmPrim.hs``) 165 | 166 | - Backends to actually compile them. LLVM should be quite easy because it 167 | supports all of this. Native backend might require more work (e.g., ``imulb`` 168 | uses implicit register operands and is not currently supported by the native 169 | backend) 170 | 171 | Additional context 172 | ------------------ 173 | 174 | - `Initial discussion`_ on ``ghc-devs`` about small primitives 175 | 176 | - Ticket about always exposing ``Word64#``/``Int64#``: `#11953`_ 177 | 178 | 179 | .. _Initial discussion: https://mail.haskell.org/pipermail/ghc-devs/2017-August/014462.html 180 | 181 | .. _#11953: https://gitlab.haskell.org/ghc/ghc/issues/11953 182 | 183 | .. _LLVM's calling convention for GHC: https://github.com/llvm-project/llvm-project-20170507/blob/e11c49f6c12a9646ef77f8781acc626bbfcae9b5/llvm/lib/Target/X86/X86CallingConv.td#L648 184 | -------------------------------------------------------------------------------- /proposals/0076-numeric-underscores.rst: -------------------------------------------------------------------------------- 1 | Underscores in Numeric Literals 2 | =============================== 3 | 4 | .. author:: Takenobu Tani 5 | .. date-accepted:: 2017-11-14 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/14473 7 | .. implemented:: 8.6.1 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | GHC supports various numeric literals such as decimal, octal, hexadecimal, binary, and floating point numbers. 13 | However, large numeric literals are hard to read. 14 | This proposal improves the readability, quality, expressiveness of numeric literals. 15 | 16 | Motivation 17 | ------------ 18 | Large numeric literals are hard to read. 19 | This easily causes a bug. 20 | For example, the following numbers are confusing: 21 | 22 | .. code-block:: none 23 | 24 | x = 10000000 -- Is this one million or ten million? 25 | y = 0x3ffffff -- Is this 4M or 64M? 26 | z = 0b000100000000 -- Which position is a 1-bit digit? 27 | 28 | Readability can be improved by separating numbers with underscores (``_``). 29 | This feature improves readability, quality and expressiveness as follows: 30 | 31 | .. code-block:: none 32 | 33 | x = 10_000_000 -- ten million 34 | y = 0x3ff_ffff -- 64M 35 | z = 0b0001_0000_0000 -- 8th bit 36 | 37 | 38 | Similar feature is introduced in some languages such as `Verilog-HDL `_ and `Rust `_ . 39 | 40 | Proposed Change Specification 41 | ----------------------------- 42 | 43 | I propose an extension to the existing syntax of numeric literals. 44 | 45 | New syntax (this proposal) 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | When the ``NumericUnderscores`` language extension is enabled, syntax is changed as follows: 48 | 49 | .. code-block:: none 50 | 51 | -- `numSpacer` is enabled with NumericUnderscores extension 52 | numSpacer = {_} 53 | 54 | decimal → digit{numSpacer digit} 55 | octal → octit{numSpacer octit} 56 | hexadecimal → hexit{numSpacer hexit} 57 | binary → binit{numSpacer binit} 58 | 59 | integer → decimal 60 | | 0 (o | O) numSpacer octal 61 | | 0 (x | X) numSpacer hexadecimal 62 | | 0 (b | B) numSpacer binary 63 | 64 | float → decimal . decimal [exponent] 65 | | decimal exponent 66 | | 0 (x | X) numSpacer hexadecimal . hexadecimal [bin_exponent] 67 | | 0 (x | X) numSpacer hexadecimal bin_exponent 68 | 69 | exponent → numSpacer (e | E) [+ | -] decimal 70 | bin_exponent → numSpacer (p | P) [+ | -] decimal 71 | 72 | -- Underscores (_) in numeric literals are simply ignored. 73 | 74 | Current syntax 75 | ~~~~~~~~~~~~~~ 76 | Current specification in `Haskell 2010 Language Report, chapter 2 `_ , `BinaryLiterals `_ , and `HexFloatLiterals `_ language extension: 77 | 78 | .. code-block:: none 79 | 80 | decimal → digit{digit} 81 | octal → octit{octit} 82 | hexadecimal → hexit{hexit} 83 | binary → binit{binit} -- BinaryLiterals 84 | 85 | integer → decimal 86 | | 0 (o | O) octal 87 | | 0 (x | X) hexadecimal 88 | | 0 (b | B) binary -- BinaryLiterals 89 | 90 | float → decimal . decimal [exponent] 91 | | decimal exponent 92 | | 0 (x | X) hexadecimal . hexadecimal [bin_exponent] -- HexFloatLiterals 93 | | 0 (x | X) hexadecimal bin_exponent -- HexFloatLiterals 94 | 95 | exponent → (e | E) [+ | -] decimal 96 | bin_exponent → (p | P) [+ | -] decimal -- HexFloatLiterals 97 | 98 | digit → ascDigit | uniDigit 99 | ascDigit → 0 | 1 | … | 9 100 | uniDigit → any Unicode decimal digit 101 | octit → 0 | 1 | … | 7 102 | hexit → digit | A | … | F | a | … | f 103 | binit → 0 | 1 -- BinaryLiterals 104 | 105 | Examples 106 | -------- 107 | The followings are examples of this proposal: 108 | 109 | use case examples 110 | ~~~~~~~~~~~~~~~~~ 111 | 112 | .. code-block:: none 113 | 114 | -- decimal 115 | million = 1_000_000 116 | billion = 1_000_000_000 117 | lightspeed = 299_792_458 118 | version = 8_04_1 119 | date = 2017_12_31 120 | 121 | -- hexadecimal 122 | red_mask = 0xff_00_00 123 | size1G = 0x3fff_ffff 124 | 125 | -- binary 126 | bit8th = 0b01_0000_0000 127 | packbits = 0b1_11_01_0000_0_111 128 | bigbits = 0b1100_1011__1110_1111__0101_0011 129 | 130 | -- float 131 | pi = 3.141_592_653_589_793 132 | faraday = 96_485.332_89 133 | avogadro = 6.022_140_857e+23 134 | 135 | -- function 136 | isUnderMillion = (< 1_000_000) 137 | 138 | clip64M x 139 | | x > 0x3ff_ffff = 0x3ff_ffff 140 | | otherwise = x 141 | 142 | test8bit x = (0b01_0000_0000 .&. x) /= 0 143 | 144 | validity examples 145 | ~~~~~~~~~~~~~~~~~ 146 | 147 | .. code-block:: none 148 | 149 | x0 = 1_000_000 -- valid 150 | x1 = 1__000000 -- valid 151 | x2 = 1000000_ -- invalid 152 | x3 = _1000000 -- invalid 153 | 154 | e0 = 0.0001 -- valid 155 | e1 = 0.000_1 -- valid 156 | e2 = 0_.0001 -- invalid 157 | e3 = _0.0001 -- invalid 158 | e4 = 0._0001 -- invalid 159 | e5 = 0.0001_ -- invalid 160 | 161 | f0 = 1e+23 -- valid 162 | f1 = 1_e+23 -- valid 163 | f2 = 1__e+23 -- valid 164 | f3 = 1e_+23 -- invalid 165 | 166 | g0 = 1e+23 -- valid 167 | g1 = 1e+_23 -- invalid 168 | g2 = 1e+23_ -- invalid 169 | 170 | h0 = 0xffff -- valid 171 | h1 = 0xff_ff -- valid 172 | h2 = 0x_ffff -- valid 173 | h3 = 0x__ffff -- valid 174 | h4 = _0xffff -- invalid 175 | 176 | Effect and Interactions 177 | ----------------------- 178 | I believe that this proposal will improve the readability, quality and expressiveness of native numeric literals without degrading performance. 179 | 180 | Costs and Drawbacks 181 | ------------------- 182 | * Implementation costs are mostly related to lexers. 183 | * Maintenance costs are related to compatibility. Compatibility can be handled with language extension of ``NumericUnderscores``. 184 | * I think the user's learning curve is not a problem. They will soon get used to it. 185 | * Syntax highlighting for text editors and code browsers is affected. 186 | 187 | Alternatives 188 | ------------ 189 | For example, these expressions are current alternatives: 190 | 191 | .. code-block:: none 192 | 193 | x = 10 * 1000 * 1000 :: Int 194 | y = [0x3ff, 0xffff] :: [Int] 195 | z = "0001 0000 0000" :: String 196 | t = 5000000 -- five sec (inline comment) 197 | 198 | However, they cause increased description cost or performance degradation. 199 | 200 | Unresolved questions 201 | -------------------- 202 | None 203 | -------------------------------------------------------------------------------- /proposals/0077-deprecate-stm-invariants.rst: -------------------------------------------------------------------------------- 1 | Deprecating STM invariant mechanism 2 | =================================== 3 | 4 | .. author:: Ben Gamari 5 | .. date-accepted:: 2018-02-03 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/14324 7 | .. implemented:: 8.6 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The invariant-checking mechanism provided by GHC's ``stm`` library is buggy and 13 | appears to be largely unused. Let's remove it. 14 | 15 | 16 | Motivation 17 | ------------ 18 | 19 | GHC's STM subsystem has long had the ability to run user-specified invariant 20 | checks when committing transactions, embodied by the ``always`` and 21 | ``alwaysSucceeds`` functions of ``Control.Monad.STM``. 22 | 23 | However, if Hackage is any indication this feature has seen very little 24 | use of the past ten years. In fact, it has very likely been quite broken 25 | (see `#14310 `_) for this entire 26 | duration yet no one noticed. Moreover, the 27 | mechanism is likely mediocre at achieving its goal of catching broken 28 | invariants due to odd interleavings of transactions as its 29 | implementation is extremely sychronization-heavy. Additionally, the 30 | mechanism currently fails to handle some corner-cases correctly 31 | (`#7930 `_). 32 | 33 | In short, the feature is complex, buggy, and not pulling its weight. 34 | 35 | 36 | Proposed Change Specification 37 | ----------------------------- 38 | For GHC 8.4.1 we mark ``Control.Monad.STM.always`` and 39 | ``Control.Monad.STM.alwaysSucceeds`` with ``DEPRECATED`` pragmas. These 40 | interfaces will be removed three major releases later. 41 | 42 | 43 | Effect and Interactions 44 | ----------------------- 45 | This will allow us to remove the invariants implementation from the runtime 46 | system. 47 | 48 | Current users of the interface have a few options to adapt their code to 49 | manually call invariant their checks where necessary. 50 | 51 | 52 | Costs and Drawbacks 53 | ------------------- 54 | The removal of the interfaces will break any existing users. 55 | 56 | Alternatives 57 | ------------ 58 | Not removing the interface. 59 | 60 | 61 | Unresolved questions 62 | -------------------- 63 | How many users does this interface have? Is it crucial to their programs' functions? 64 | 65 | 66 | Implementation Plan 67 | ------------------- 68 | I, Ben Gamari, will implement this. 69 | -------------------------------------------------------------------------------- /proposals/0080-type-level-type-applications.rst: -------------------------------------------------------------------------------- 1 | Type-level type applications 2 | ============================ 3 | 4 | .. author:: Richard Eisenberg 5 | .. date-accepted:: 2018-03-01 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/12045 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal is `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | .. _`#12045`: https://gitlab.haskell.org/ghc/ghc/issues/12045 13 | 14 | Allow the use of type applications at the type level. For example, 15 | we could write:: 16 | 17 | 'Just @Nat 18 | 19 | instead of:: 20 | 21 | 'Just :: Nat -> Maybe Nat 22 | 23 | 24 | Motivation 25 | ------------ 26 | There are two major motivations: 27 | 28 | 1. To allow users to get the power and convenience of explicit type 29 | applications at the type level as well as the term level. 30 | 31 | 2. To allow ``-fprint-explicit-kinds`` and the ``Show`` instance for 32 | ``TypeRep`` to produce more readable output. Currently, 33 | ``show (typeRep @('Just 3))`` produces ``"'Just Nat 3"``, making 34 | no distinction between levels. With the proposed change, we could 35 | quite legitimately produce ``"'Just @Nat 3"``, which seems much clearer. 36 | 37 | 38 | Proposed Change Specification 39 | ----------------------------- 40 | Allow visible type application in types as well as terms. In precisely 41 | the same way that it currently is used to reduce ``forall``\s in terms, 42 | it will reduce ``forall``\s in types. This new behavior will be controlled 43 | by the ``-XTypeApplications`` extension. 44 | 45 | Specifically: 46 | 47 | 1. Add new parsing rules to types allowing ``@`` to appear before a type argument. 48 | 49 | 2. Currently, GHC tracks three *visibilities*: *required*, *specified*, and *inferred*. 50 | A required argument must be applied at every call site. These are normal arguments, 51 | like the ``a`` argument to ``Maybe a``. Specified arguments are arguments that are 52 | normally omitted but can be supplied explicitly with the use of ``@``. For example, 53 | the ``k`` in ``data Proxy :: forall k. k -> Type`` is specified. Inferred arguments 54 | are not available for explicit application, like the kind of ``a`` in ``data Proxy2 a``. 55 | 56 | With visible type application in types, users could provide explicit instantiations 57 | of specified arguments. 58 | 59 | In an extension to existing rules, a variable must be mentioned somewhere in the Haskell 60 | source to be specified. A variable that is never written in the source is inferred. 61 | 62 | 3. Promoted data constructor arguments have the same visibilities as the unpromoted data 63 | constructor. 64 | 65 | 4. GHC's current behavior of implicitly quantifying over type variables used in type 66 | signatures is unaffected. If a type variable is mentioned only in a visible type 67 | application, it is still implicitly quantified. 68 | 69 | Effect and Interactions 70 | ----------------------- 71 | 72 | This new feature would work in pattern signatures (that is, a type signature ascribing a type to a term-level pattern) and would have the capability of binding a scoped type variable. Viz:: 73 | 74 | data Ex where 75 | MkEx :: forall k (a :: k). Proxy (a :: k) -> Ex 76 | 77 | foo (MkEx (p :: Proxy @k a)) = ... k is in scope here (along with a) ... 78 | 79 | Costs and Drawbacks 80 | ------------------- 81 | As a user, I was 82 | quite surprised to find that this didn't work already, so I don't think 83 | the learning cost will be high. 84 | 85 | The development costs should be relatively low. Instantiation in types is 86 | already lazy, and so type application in types will be much easier to implement 87 | than type application in terms was. 88 | 89 | Alternatives 90 | ------------ 91 | I am not aware of any existing alternatives. 92 | 93 | 94 | Unresolved questions 95 | -------------------- 96 | Should we change the behavior of ``:kind`` to match that of ``:type``? Currently, the latter 97 | does instantiation while the former does not. This means that there is no screaming need 98 | to introduce a ``:kind +v``, because ``:kind`` is already analogous to ``:type +v``. Perhaps 99 | this is confusing though. 100 | 101 | 102 | Implementation Plan 103 | ------------------- 104 | Richard Eisenberg (@goldfirere) is happy to advise someone who wants to take this on. Or he 105 | will implement himself someday. 106 | -------------------------------------------------------------------------------- /proposals/0081-forall-arrow.rst: -------------------------------------------------------------------------------- 1 | A syntax for visible dependent quantification 2 | ============================================= 3 | 4 | .. author:: Richard Eisenberg 5 | .. date-accepted:: 2018-09-30 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/16326 7 | .. implemented:: 8.10 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | GHC 8.0 has support for visible dependent quantification in kinds. For example, GHC 8 will accept :: 13 | 14 | data T k (a :: k) 15 | 16 | Note that any (fully-applied) use of ``T`` has to mention both a kind and a type. For example, 17 | ``T Nat 3`` and ``T Type Int`` are well-typed. If you ask GHCi for the kind of ``T``, it tells 18 | you ``forall k -> k -> *`` (with ``-fprint-explicit-foralls``). Note that there is no ``.`` after 19 | the ``forall``. Instead, this kind makes ``k`` a visible, dependent type variable. It's *visible* 20 | because every (fully-applied) use of ``T`` must pass in a value for ``k`` visibly (explicitly). 21 | It's *dependent* because ``k`` appears later in the kind of ``T``. The ability to have visible, 22 | dependent quantifiees is a new feature in GHC 8, available only in kinds. (There's no way to do 23 | this in terms.) 24 | 25 | The syntax ``forall k -> k -> *`` that is printed in GHCi for these kinds is not currently parsed. 26 | This proposal proposed to add this kind format to the language as a first-class kind. 27 | 28 | This proposal is viable on its own, but it may be best considered in the context of other 29 | quantifiers needed to support dependent types. See `#102 `_. 30 | 31 | Motivation 32 | ------------ 33 | 34 | Currently, GHC allows the user to define a type with a visible, dependent quantifiers in its kind, 35 | but it offers no way to write the kind directly. This is just plain silly. 36 | 37 | (Historical note: the reason this happened is that I got early feedback claiming that ``forall k -> ...`` 38 | was poor syntax, and I was reticent to add it to the language with ``-XTypeInType``. However, now that 39 | this proposals process is active, I'm happy to propose the new syntax where it can get debated in the 40 | open and perhaps refined.) 41 | 42 | A useful example of how this construct might be used is an alternative syntax for ``TypeRep``. We can 43 | imagine :: 44 | 45 | TypeRepV :: forall k -> k -> Type -- "V" for visible 46 | 47 | as a companion to :: 48 | 49 | TypeRep :: forall k. k -> Type -- we have this today 50 | 51 | Now, if someone wants to operate on 52 | a type representation for some type of kind ``Type -> Type``, they could say :: 53 | 54 | foo :: TypeRepV (Type -> Type) a -> ... 55 | 56 | and GHC would easily infer that ``a`` should have kind ``Type -> Type``. 57 | 58 | Proposed Change Specification 59 | ----------------------------- 60 | Add a new bit of syntax for types (= kinds) that looks like this:: 61 | 62 | 'forall' tv_bndrs '->' ctype 63 | 64 | where ``ctype`` is the point within GHC's grammar (as implemented in its 65 | `parser `_) 66 | where the current ``'forall' tv_bndrs '.' ctype`` rule lives. The meaning will 67 | be identical to that of the existing ``forall`` construct, except that the 68 | ``tv_bndrs`` will be visible. 69 | 70 | (NB: The ``'forall'`` construct in the parser also accepts ``∀``.) 71 | 72 | This new construct will be rejected in any context that is unambiguously a 73 | type for a term. (For example, it will be rejected in type signatures of 74 | terms, but allowed in type synonyms, which can be used in kinds.) No 75 | term-level definition can have a type that has a visible dependent quantifier. 76 | 77 | To wit, this new construct would be forbidden in the following places (with examples 78 | of rejected constructs): 79 | 80 | * The type ascription of a ``forall``\-bound term variable in a ``RULE``:: 81 | 82 | {-# RULES "blah" forall a -> id a = a #-} 83 | 84 | * The type of a foreign import/export:: 85 | 86 | foreign export ccall freeStablePtr :: forall a -> StablePtr a -> IO () 87 | 88 | * A type signature for a term-level variable:: 89 | 90 | id :: forall a -> a -> a 91 | 92 | * The type in a ``SPECIALISE`` or ``SPECIALISE_INLINE`` or ``SPECIALISE instance`` pragma:: 93 | 94 | {-# SPECIALISE foldM :: forall a b -> (a -> b -> IO a) -> a -> [b] -> IO a #-} 95 | 96 | * An expression type ascription:: 97 | 98 | zipWith ((<>) :: forall a -> Maybe a -> Maybe a -> Maybe a) xs ys 99 | 100 | * A pattern synonym type signature:: 101 | 102 | pattern Nil :: forall a -> [a] 103 | 104 | * A type signature in a pattern:: 105 | 106 | isJust (x :: forall a -> Maybe a) = ... 107 | 108 | * A GADT data constructor type:: 109 | 110 | data T where 111 | MkT :: forall a -> a -> T 112 | 113 | Naturally, the new syntax is forbidden anywhere that ``forall`` is currently 114 | forbidden (for example, in an argument position of a type family). 115 | 116 | Effect and Interactions 117 | ----------------------- 118 | Shouldn't be any untoward interactions. Template Haskell will have to be updated, and we'll have to 119 | make sure no terms can get these strange new types. 120 | 121 | Note that the new construct *can* be used in higher-rank scenarios:: 122 | 123 | data S :: (forall k -> k -> Type) -> Type 124 | 125 | will accept the ``T`` in the introduction as an argument, but it won't accept ``Data.Proxy``\'s 126 | ``Proxy``, as ``Proxy`` takes its argument invisibly. Perhaps one day we can devise a way 127 | to coerce visibilities to allow ``S`` to take ``Proxy`` as an argument, but not today. 128 | 129 | Costs and Drawbacks 130 | ------------------- 131 | It's one more construct that has to be maintained, which is a non-negligible cost. But, I argue that 132 | the language simply has a strange surface area without this feature, where a type exists that cannot 133 | be written down. 134 | 135 | A drawback of the design as proposed is that the signifier of the visible/invisible distinction can 136 | be far away from individual variables. For example, consider ``forall a b c d.`` and ``forall a b c d ->``. 137 | You have to scan for the ``.`` or the ``->`` before you know what kind of quantification is at hand. 138 | 139 | Alternatives 140 | ------------ 141 | 142 | I don't have any good ones. Do you? 143 | 144 | Unresolved questions 145 | -------------------- 146 | None right now, other than bikeshedding this syntax. 147 | 148 | 149 | Implementation Plan 150 | ------------------- 151 | I or a close collaborator volunteer to implement. 152 | -------------------------------------------------------------------------------- /proposals/0094-as-patterns-synonyms.rst: -------------------------------------------------------------------------------- 1 | As patterns in pattern synonyms 2 | ============== 3 | 4 | .. author:: Simon Peyton Jones 5 | .. date-accepted:: 2018-03-18 6 | .. ticket-url:: Leave blank. This will eventually be filled with the 7 | ticket URL which will track the progress of the 8 | implementation of the feature. 9 | .. implemented:: 8.6 10 | .. highlight:: haskell 11 | .. header :: This proposal was `discussed at this pull request `_ and implemented in commit `411a97e2 `_. 12 | .. contents:: 13 | 14 | As-patterns (and n+k patterns) are currently disallowed in unidirectional pattern synonyms. There is no good reason for this. 15 | I propose that we lift the restriction. 16 | 17 | Motivation 18 | ------------ 19 | Why lift the restriction on as-patterns? 20 | 21 | * If the restriction is lifted, then *all* patterns become OK in unidirecitonal pattern synonyms. 22 | Having no exceptions makes our users' lives easier: it is a real prize. In fact the user manual already claims (falsely) that there are no such restrictions. 23 | 24 | * A slab of code can simply be deleted from the compiler. 25 | 26 | * The semantics of matching does not change at all. 27 | 28 | What's not to like? 29 | 30 | I regard n+k patterns, which are deprecated anyway, as a side issue, but they should be treated 31 | uniformly. 32 | 33 | For bidirectional pattern synonyms, there are already many restrictions on what patterns you can write, and rightly so because a bidirectional pattern synonym must be used both to pattern match and to construct values. I do not propose any change in the rules for bidirectional pattern synonyms. 34 | 35 | Proposed Change Specification 36 | ----------------------------- 37 | There is only one change: 38 | 39 | * Allow as-patterns and n+k patterns in unidirectional pattern synonyms. 40 | 41 | For example, this definition would become legal. 42 | 43 | :: 44 | 45 | patttern MP x y <- x@(Just y) 46 | 47 | :: 48 | 49 | Currently this is rejected. Why? Because of worries about what this might mean (see #9793) : 50 | 51 | :: 52 | 53 | f (MP (Just z) v) = e 54 | 55 | :: 56 | 57 | With a "macro-expansion" model of pattern synonyms, that might be equivalent to 58 | 59 | :: 60 | 61 | f (Just z)@(Just v) = e 62 | 63 | :: 64 | 65 | which is a jolly funny pattern. But the semantics of pattern synonyms are NOT simply macro-expansion: see `the paper (Section 5) `_. 66 | Rather, their semantics is given thus: 67 | 68 | * To match a pattern ``(P p1 .. pn)``, where ``P`` is a pattern synonym defined by ``P x1 ... xn <- p``, 69 | match the value aginst ``p`` (binding x1..xn); and then match the ``xi`` against ``pi``. 70 | 71 | This description works perfectly for as-patterns. For example to match a value against ``(MP (Just z) v)``, 72 | first match the value against ``x@(Just y)``, binding x and y; and then match ``x`` against ``Just z`` and ``y`` against ``v``. 73 | 74 | 75 | 76 | 77 | Effect and Interactions 78 | ----------------------- 79 | None that I can see. It just lifts a restriction. 80 | 81 | Note that, just as it is possible to write a view pattern that never matches, so it is 82 | possible to write a pattern synonym that never matches using an as-pattern. For example 83 | 84 | :: 85 | 86 | patttern MP x y <- x@(Just y) 87 | 88 | f (MP Nothing v) = ... 89 | 90 | :: 91 | 92 | According to the rules, we first match the argument ``v`` against the RHS of the pattern synonym ``x@(Just y)``. Maybe that fails; if so the match fails. Maybe it succeeds, binding ``x`` to ``Just v2`` and ``y`` to ``v2``. Now match the value of ``x`` (namely ``Just v2``) against ``Nothing``. That fails, so the overall match fails. So the rules say that this pattern will never match. 93 | 94 | There is nothing wrong with this; it is possible now, and it remains possible. (GADT patterns can also be guaranteed to fail.) 95 | 96 | Costs and Drawbacks 97 | ------------------- 98 | Implementation is a matter of deleting code. 99 | 100 | Alternatives 101 | ------------ 102 | One could imagine extending the syntax of patterns, to include ``pat1@pat2``, with matching semantics thus: 103 | 104 | * To match a pattern ``p1@p2`` aagainst a value ``v``, match ``p1`` against ``v`` (binding some variables ``x1..xn``), the match ``p2`` against ``v`` (binding some variables ``y1..ym``). If both matches succeed, the overall match succeeds, binding ``x1..xn,y1..ym``. 105 | 106 | That would make a lot of sense: ``p1@p2`` would be an and-pattern, dual to the proposed or-patternns. I'm not actually proposing that change here; it would be a very sensible follow-on. But it the committee prefers, it could even be accepted right away. 107 | 108 | Indeed, via a pattern synonym you can get an and-pattern 109 | 110 | :: 111 | 112 | pattern And x y <- x@y 113 | 114 | :: 115 | 116 | Now, according to the rules, ``And p1 p2`` will match only if both ``p1`` and ``p2`` match. 117 | 118 | 119 | Unresolved questions 120 | -------------------- 121 | None that I can see 122 | 123 | Implementation Plan 124 | ------------------- 125 | I can implement it. 126 | -------------------------------------------------------------------------------- /proposals/0103-no-kind-vars.rst: -------------------------------------------------------------------------------- 1 | Treat kind variables and type variables identically in ``forall`` 2 | ================================================================= 3 | 4 | .. author:: Richard Eisenberg 5 | .. date-accepted:: 2018-05-22 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/15264 7 | .. implemented:: 8.10 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | GHC has supported kind polymorphism since version 7.4. Kind polymorphism allows (among 14 | other features) users to specify *kind variables* in their declarations. When the 15 | feature was first introduced, type variables and kind variables were wholly separate, 16 | introduced in different syntactic contexts and subject to different rules around 17 | type inference. (For example, all kind variables were always of kind ``BOX``; abstraction 18 | over kind constructors like a promoted ``Maybe`` was not allowed.) Of particular interest, 19 | GHC 7 offered no way to explicitly bring a kind variable into scope. Instead, users just 20 | mentioned ``k`` in an appropriate context and the kind variable came into being. 21 | 22 | Because of this legacy, current GHC still treats kind variables differently than type 23 | variables, as expanded in the Motivation_ section, below. 24 | 25 | Under this proposal, kind variables and type variables would be treated identically, 26 | removing this legacy distinction. This is a *simplification* over the status quo. 27 | 28 | Note that this proposal assumes that proposal `#83`_ has been accepted, meaning that 29 | explicit quantification over kind variables is possible with only ``-XPolyKinds``, 30 | not needing ``-XTypeInType``. 31 | 32 | .. _`#83`: https://github.com/goldfirere/ghc-proposals/blob/no-type-in-type/proposals/0000-no-type-in-type.rst 33 | 34 | 35 | Motivation 36 | ------------ 37 | There are two ways in which current treatment 38 | type and kind variables differ. This section enumerates these, showing that they are awkward 39 | to understand and maintain. 40 | 41 | We will consider the following collection of type signatures:: 42 | 43 | f :: a -> a 44 | g :: forall a. a -> a 45 | h :: forall a. a -> b -> a 46 | i :: Proxy (a :: k) -> () 47 | j :: forall a. Proxy (a :: k) -> () 48 | 49 | 50 | 1. **The "forall-or-nothing" rule** 51 | 52 | Currently, all of the signatures above are accepted except ``h``. GHC has a rule I call the 53 | "forall-or-nothing" rule: if you begin a type signature with an explicit ``forall``, 54 | you must specify *all* the type variables brought into scope. The idea behind 55 | forall-or-nothing is that if a user is writing an explicit ``forall``, then they 56 | should be protected if they make an accidental misspelling of a variable later on. 57 | 58 | However, because kind variables initially couldn't be introduced in a ``forall``, 59 | the forall-or-nothing rule doesn't apply to variables mentioned at least once after 60 | a ``::`` in a type. So, even though ``j`` doesn't explicitly introduce ``k``, the 61 | type is accepted as in compliance with the forall-or-nothing rule. A consequence 62 | of this is that there is no way for a type signature to indicate that a kind variable 63 | is meant to come from an outer scope. 64 | 65 | 2. **Scoped type variables** 66 | 67 | An explicit ``forall`` in a type signature does double-duty: not only does it bring 68 | a type variable into scope in the type, that type variable is also in scope in the 69 | definition of a function (with ``-XScopedTypeVariables``). Now we must ask: how 70 | do we bring a *kind* variable into scope? GHC brings kind variables into scope 71 | whenever there is a ``forall`` present in the type signature, regardless of whether 72 | or not the kind variable was explicitly included in the ``forall``. Referring 73 | back to the type signatures above, this means that ``k`` is brought into scope 74 | in the body of ``j`` but not ``i``. It would be more consistent to have to put 75 | ``k`` in the explicit list of variables brought into scope. 76 | 77 | Proposed Change Specification 78 | ----------------------------- 79 | 80 | Type variables and kind variables will be treated identically in types. 81 | Specifically: 82 | 83 | 1. With ``-Wcompat``, warn if a kind variable is brought into scope implicitly in 84 | a type with an explicit ``forall``. This applies to type signatures and to other 85 | contexts that allow a ``forall`` with the forall-or-nothing rule in effect (for example, 86 | class instances). 87 | 88 | 2. Two releases after `#83`_ is implemented, make it an error to bring a kind variable 89 | into scope implicitly in a type with an explicit ``forall`` and where the forall-or-nothing 90 | rule is in effect. 91 | 92 | Effect and Interactions 93 | ----------------------- 94 | This will not be backward compatible, because more explicit listing of kind variables 95 | will be necessary. (To wit, example ``j`` above would be newly rejected.) The fix will 96 | be to explicitly list kind variables in ``forall`` clauses. However, this has been 97 | possible only with ``-XTypeInType``, not simply ``-XPolyKinds``. Thus, it seems best 98 | to wait until 2 releases after `#83`_ is implemented, so that adding the kind variable 99 | to the ``forall`` will not require adding a new extension. 100 | 101 | Costs and Drawbacks 102 | ------------------- 103 | This is a simplification to the specification and implementation of GHC, 104 | at least after the ``-Wcompat`` migration help 105 | is done. I can't think of any drawbacks. 106 | 107 | 108 | Alternatives 109 | ------------ 110 | 111 | * Keep status quo, but that's hard to justify. 112 | 113 | * Don't wait for two releases after `#83`_, given that the fix is compatible 114 | with three releases if ``-XTypeInType`` is enabled. 115 | 116 | * Treat the ``k`` in ``forall (a :: k). Proxy a -> ()`` specially, allowing 117 | this syntax to bring ``k`` into scope. Specifically, any unbound variable 118 | mentioned in a kind signature of a type variable binder could be brought 119 | into scope. This was suggested on the GitHub thread, but I find it to be 120 | an unnecessary special case, just to preserve a sliver of legacy behavior 121 | that we needn't preserve. I'm listing it here as a viable, consistent alternative, 122 | however. 123 | 124 | Unresolved questions 125 | -------------------- 126 | None that I know of. 127 | 128 | 129 | Implementation Plan 130 | ------------------- 131 | I or a close collaborator volunteers to implement. Offers of help are welcome. 132 | -------------------------------------------------------------------------------- /proposals/0106-type-data.rst: -------------------------------------------------------------------------------- 1 | Define Kinds Without Promotion 2 | ============================== 3 | 4 | .. author:: Iavor Diatchki 5 | .. date-accepted:: 2018-09-12 6 | .. ticket-url:: 7 | .. implemented:: 8 | .. header:: This proposal was `discussed at this pull request `_. 9 | .. highlight:: haskell 10 | .. contents:: 11 | 12 | 13 | This proposal introduces a language construct for defining kinds without 14 | having to promote types. For example, this is how we would 15 | define a new kind ``Universe``, with three members:: 16 | 17 | type data Universe = Character | Number | Boolean 18 | 19 | Motivation 20 | ---------- 21 | 22 | Currently, GHC supports defining new kinds using data promotion, which means 23 | that a single ``data`` declaration introduces both a type with value 24 | constructors, and a kind with type constructors. In some cases this 25 | alleviates the need for duplicated declarations (e.g., ``Bool``), however, 26 | in many common cases using promotion leads to clutter. Consider, for example, 27 | the following code pattern, which is very common when defining Haskell EDSLs:: 28 | 29 | {-# Language DataKinds, GADTs #-} 30 | 31 | data Universe = Character | Number | Boolean 32 | 33 | type Character = 'Character 34 | type Number = 'Number 35 | type Boolean = 'Boolean 36 | 37 | data Type u where 38 | CharacterRepr :: Type Character 39 | NumberRepr :: Type Number 40 | BooleanRepr :: Type Boolean 41 | 42 | The first issue is the collection of type synonyms, one for each constructor. 43 | They provide proper names for the promoted types, which has a number of 44 | benefits: 45 | 46 | - we can refer to the types in export lists, 47 | - we get an ambiguity error if another module happens to define a type with the same name; this is not the case if using the name of a promoted type directly---"normal" types silently "win", and the promoted type is ignored without an error. 48 | - we can refer to the types from other modules without having to enable ``{-# DataKinds #-}`` 49 | 50 | The second issue is that the value constructors introduced by ``Universe`` 51 | are unused, but still clutter up the name space. As a result, 52 | we have to use different names in the GADT that defines the value-level 53 | representatives for the members of ``Universe``. 54 | 55 | Relevant links: 56 | 57 | - GHC ticket for the same idea: https://gitlab.haskell.org/ghc/ghc/issues/6024 58 | - An older proposal for the same idea: https://gitlab.haskell.org/ghc/ghc/wikis/ghc-kinds/kinds-without-data 59 | - Example of real code where the clutter is a problem: 60 | https://github.com/GaloisInc/crucible/blob/master/crucible/src/Lang/Crucible/Types.hs#L351 61 | 62 | 63 | Proposed Change 64 | --------------- 65 | 66 | We propose to add a new GHC extension called ``{-# TypeData #-}``. 67 | When this extension is enabled, the ``data`` keyword in a data declaration 68 | may be preceeded by ``type``, which signifies that this declaration affects 69 | only the types: the LHS introduces a new kind, and the RHS introduces type 70 | constructors that belong to this kind. 71 | 72 | Semantically, the new declaration should work in the same way as kinds 73 | introduced by promotion, with the following differences: 74 | 75 | - The names of the "promoted" constructors are not prefixed by ``'`` and match 76 | the names in the declaration exactly. 77 | - The declaration does not introduce any value-level constructors. 78 | 79 | This allows a much more direct declaration of the example from the 80 | motivation section:: 81 | 82 | {-# Language TypeData, GADTs #-} 83 | 84 | type data Universe = Character | Number | Boolean 85 | 86 | data Type u where 87 | Character :: Type Character 88 | Number :: Type Number 89 | Boolean :: Type Boolean 90 | 91 | The following table summarizes the names introduced by normal 92 | `data` and `type data` declarations. 93 | 94 | ================================= =============== =============== 95 | Declaration Value Namespace Type Namespace 96 | ================================= =============== =============== 97 | ``data T = MkT`` ``MkT`` ``T`` 98 | ``type data T = MkT`` (nothing) ``T``, ``MkT`` 99 | ================================= =============== =============== 100 | 101 | 102 | Differences From Ordinary Data Declarations 103 | ------------------------------------------- 104 | 105 | The `type data` declarations described in this proposal correspond 106 | to a restricted form of `data` declaration. In particular, here 107 | are some restrictions: 108 | 109 | * **No Constructor Name Shadowing** 110 | Since in GHC types and kinds share the same namespace, 111 | the following declaration will be rejected:: 112 | 113 | type data T = T // Invalid 114 | 115 | Thus, when using a `type data` the constructors must have different 116 | names from the kind on the left of the ``=`` sign. 117 | 118 | * **No Record Selectors** 119 | Record selectors are not supported. One could imagine 120 | adding some support for that (e.g., by generating selector / updater type functions) 121 | but at the moment it is not clear that it is neccessary, or what the right design 122 | should be, so we leave it out of this proposal. 123 | 124 | * **No Quantifiers** 125 | Existential and universal quantifiers in data declarations are not supported at the moment, 126 | as we don't know how they might work. 127 | 128 | * **No Strictness Annotations and UNPACK pragmas** 129 | These don't really make sense at the type level. 130 | 131 | Drawbacks 132 | --------- 133 | There are currently no known draw-backs to this feature. 134 | 135 | Alternatives 136 | ------------ 137 | 138 | Don't do this, and just keep using data promotion. 139 | 140 | Unresolved Questions 141 | -------------------- 142 | 143 | There are currently no known unresolved questions. 144 | -------------------------------------------------------------------------------- /proposals/0121-resize-boxed.rst: -------------------------------------------------------------------------------- 1 | Offer more array resizing primitives 2 | ==================================== 3 | 4 | .. author:: David Feuer 5 | .. date-accepted:: 2018-07-02 6 | .. ticket-url:: 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | At present, we have ``shrinkMutableByteArray#`` and ``resizeMutableByteArray#``. 13 | We lack resizing primitives for other types of arrays: ``MutableArray#``, 14 | ``SmallMutableArray#``, the soon-to-be-deprecated ``MutableArrayArray#``, and 15 | the soon-to-be-implemented ``UnliftedArray#`` (see 16 | `Proposal 21 `_). 17 | 18 | I propose we add them (with the exception of the ``MutableArrayArray#`` 19 | version), along with analogues of ``getSizeofMutableByteArray#`` to match. 20 | 21 | Motivation 22 | ------------ 23 | 24 | Suppose I want to convert a list to an array. One option is to take the length 25 | of the list, allocate an array, and then copy the list into the array. This is 26 | simple, but it involves a lot of pointer-chasing and cannot release any list 27 | conses until the list has been fully realized. Another option is to use array 28 | doubling: allocate a small array, copy elements into it until it is full, then 29 | expand the array and continue. 30 | 31 | At present, the array doubling approach is somewhat inefficient. The main 32 | problem, and certainly the one most susceptable to a solution, is that once the 33 | list runs out, we're likely left with a partially filled array. We have to 34 | allocate *another* array of the correct size, then copy the elements over. If 35 | we could simply shrink the array at the end, we could avoid this useless 36 | operation and let the garbage collector clean up the mess the next time it runs. 37 | 38 | Proposed Change Specification 39 | ----------------------------- 40 | Add ``shrinkMutableArray#``, ``shrinkSmallMutableArray#``, ``shrinkUnliftedArray#``, 41 | ``getSizeofMutableArray#``, ``getSizeofSmallMutableArray#``, and 42 | ``getSizeofMutableUnliftedArray#`` to match the ``ByteArray#`` versions. 43 | 44 | Add a resizing operation for each array type. Unlike ``ByteArray#``, these 45 | can't simply fill with zeros. The simplest option, and I suspect the most 46 | useful, would be to take a filler value to use if the array expands :: 47 | 48 | resizeArray# :: MutableArray# s a -> Int# -> a -> State# s -> (#State# s, MutableArray# s a#) 49 | 50 | Effect and Interactions 51 | ----------------------- 52 | 53 | The most obvious downside is that ``sizeofMutableArray#``, ``sizeofSmallMutableArray``, 54 | and ``sizeofMutableUnliftedArray#`` will cease to be reliable and we will have to add 55 | analogues of ``getSizeofMutableByteArray#`` to supplant them. This will break existing 56 | user code, but I doubt most of it will be very hard to fix. 57 | 58 | Costs and Drawbacks 59 | ------------------- 60 | I wouldn't anticipate terribly expensive development or maintenance. Learnability 61 | shouldn't be affected much. 62 | 63 | I see two downsides: 64 | 65 | * There's simply one more mutable thing programmers might have to 66 | keep track of. 67 | 68 | * Whereas ``sizeofMutableArray#`` can be reordered arbitrarily, 69 | ``getSizeofMutableArray#`` could not be. Most of the time, this 70 | isn't an issue, but I imagine it might reduce performance of 71 | bounds-checked array operations under some circumstances. 72 | 73 | Alternatives 74 | ------------ 75 | Doing nothing is always a popular alternative. 76 | 77 | Unresolved questions 78 | -------------------- 79 | 80 | Implementation Plan 81 | ------------------- 82 | (Optional) If accepted who will implement the change? Which other ressources and prerequisites are required for implementation? 83 | -------------------------------------------------------------------------------- /proposals/0125-type-annotated-quoters.rst: -------------------------------------------------------------------------------- 1 | Type Annotated Quoters 2 | ====================== 3 | 4 | .. date-accepted:: 2019-08-01 5 | .. ticket-url:: 6 | .. author:: winterland1989 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | The existing ``QuasiQuoter`` type is capable of producing expressions, 14 | but cannot describe the types of those expressions. We propose adding a 15 | ``TQuasiQuoter a`` type capable of producing expressions of type ``a``. 16 | 17 | Motivation 18 | ---------- 19 | 20 | ``QuasiQuoter`` is a powerful tool to do compilation time code 21 | construction, but the type ``QuasiQuoter`` is rather uninformative — 22 | especially when it’s used exclusively as an expression splice. 23 | ``QuasiQuoter``\ s which appear in haddock documentation don’t describe 24 | their resulting types, requiring a convention of comments. This is 25 | clearly against the spirit of a language with a typesystem as strong as 26 | Haskell’s. 27 | 28 | Furthermore, by exposing the type of the resulting expression, a typed 29 | quasiquoter can participate in typechecking. 30 | 31 | Proposed Change Specification 32 | ----------------------------- 33 | 34 | We will introduce a new datatype in ``Language.Haskell.TH.Quote``: 35 | 36 | .. code:: haskell 37 | 38 | data TQuasiQuoter a = TQuasiQuoter 39 | { quoteTExp :: String -> Q (TExp a) 40 | } 41 | 42 | and will add new syntactic sugar when ``-XTemplateHaskell`` is enabled: 43 | 44 | .. code:: haskell 45 | 46 | [someTQQ|| hello world ||] 47 | 48 | whose desugaring is: 49 | 50 | .. code:: haskell 51 | 52 | $$(quoteTExp someTQQ "hello world") 53 | 54 | This new typed quasiquoter syntax is identical to untyped quasiquoters, 55 | except that it requires double bars. All of the `usual rules around 56 | quasiquoted 57 | strings `__ 58 | apply here. 59 | 60 | Typed quasiquoters participate in typechecking and unification. We can 61 | put given constraints on a value of ``TQuasiQuoter``, and they will be 62 | available as usual in its definition. For example, the following is 63 | allowed: 64 | 65 | .. code:: haskell 66 | 67 | str :: IsString a => TQuasiQuoter a 68 | str = TQuasiQuoter $ \a -> [|| fromString a ||] 69 | 70 | as is its concrete use: 71 | 72 | .. code:: haskell 73 | 74 | someText :: Text 75 | someText = [str|| hello world ||] 76 | 77 | and polymorphic use: 78 | 79 | .. code:: haskell 80 | 81 | something :: IsString a => a 82 | something = [str|| hello world ||] 83 | 84 | Examples 85 | -------- 86 | 87 | We can use a typed quasiquoter to implement safe custom ``Num``\ eric 88 | types, which can’t be overflowed at compile-time. While 89 | ``-Woverflowed-literals`` can help with built-in types, it won’t help 90 | for custom types! 91 | 92 | .. code:: haskell 93 | 94 | checkedNum 95 | :: forall a 96 | . (Bounded a, Num a, Integral a, Typeable a) 97 | => TQuasiQuoter a 98 | checkedNum = TQuasiQuoter $ \str -> 99 | let minVal = fromIntegral $ minBound @a 100 | maxVal = fromIntegral $ maxBound @a 101 | val = read @Integer str 102 | in if minVal <= val && val <= maxVal 103 | then [|| fromInteger val ||] 104 | else fail $ mconcat 105 | [ show val 106 | , " is out of bounds for " 107 | , show (typeRep $ Proxy @a) 108 | ] 109 | 110 | Additionally, @yav gives an example in which we parse an AST from a 111 | string, and then separately compile that down to a ``TExp``: 112 | 113 | .. code:: haskell 114 | 115 | 116 | data Expr = Fun String Expr | Add Expr Expr | Var String 117 | deriving Show 118 | 119 | type Code a = Q (TExp a) 120 | 121 | -- Language quoter 122 | lam :: TQuasiQuoter Expr 123 | lam = TQuasiQuoter $ \input -> 124 | case pExpr (words input) of 125 | Just(e,[]) -> e 126 | _ -> fail "Parse error" 127 | 128 | pExpr :: [String] -> Maybe (Code Expr, [String]) 129 | pExpr s = case s of 130 | "ADD" : s1 -> 131 | do (a,s2) <- pExpr s1 132 | (b,s3) <- pExpr s2 133 | pure ([|| Add $$a $$b ||], s3) 134 | 135 | "FUN" : v : "->" : s1 -> 136 | do (a,s2) <- pExpr s1 137 | pure ([|| Fun v $$a ||] , s2) 138 | 139 | x : s1 -> 140 | pure ([|| Var x ||], s1) 141 | 142 | data Val = VFun (Val -> Val) | VInt Int | VErr 143 | 144 | compile :: [(String,Code Val)] -> Expr -> Code Val 145 | compile env expr = 146 | case expr of 147 | Fun x e -> [|| VFun (\i -> $$(compile ((x, [|| i ||]) : env) e)) ||] 148 | 149 | Var x -> case lookup x env of 150 | Just i -> i 151 | _ -> [|| VErr ||] 152 | 153 | Add x y -> [|| case ($$(compile env x), $$(compile env y)) of 154 | (VInt x, VInt y) -> VInt (x + y) 155 | _ -> VErr ||] 156 | 157 | Effect and Interactions 158 | ----------------------- 159 | 160 | For expression quoter writers, adding ``TQuasiQuoter a`` mainly reduce 161 | the documentation burden since the result expression’s type is already 162 | annotated. Users can spot the result type much more easily and become 163 | more confident in using these quoters. When beginners click through the 164 | ``TQuasiQuoter`` document link, they’re supposed to get the basic 165 | knowledge on how to enable some language extensions and splice quoters 166 | into their code. 167 | 168 | `simonpj `__ raises another point, that this 169 | proposal will improve error messages, consider: 170 | 171 | .. code:: haskell 172 | 173 | qq :: TQuasiQuoter Char 174 | qq = ... 175 | 176 | blah = [qq|| unicode 78 ||] && True 177 | 178 | With existing quasi-quote machinery we’d first have to run ``qq``, 179 | splice in the resulting syntax tree, and then complain if it didn’t 180 | typecheck. With a typed quasi-quoter we can complain right away: qq 181 | returns a ``TExp Char`` and that doesn’t fit somewhere a ``Bool`` is 182 | needed. 183 | 184 | Finally, this proposal finishes the syllogism that 185 | ``Exp : QuasiQuoter :: TExp : ?``. 186 | 187 | Alternatives 188 | ------------ 189 | 190 | In fact this proposal is inspired by the `Compile-time literal 191 | values `__ 192 | proposal, and shared some goals, but this proposal is more about trying 193 | to solve an existing issue with current quoters. 194 | 195 | Implementation Plan 196 | ------------------- 197 | 198 | `Matthew Pickering `__ has graciously 199 | offered to implement this, and 200 | `sighingnow `__ was nominated by the 201 | original author of this proposal. 202 | -------------------------------------------------------------------------------- /proposals/0128-scoped-type-variables-types.rst: -------------------------------------------------------------------------------- 1 | Allow ScopedTypeVariables to refer to types 2 | =========================================== 3 | 4 | .. author:: Joachim Breitner 5 | .. date-accepted:: 2018-08-04 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/15050 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The ``ScopedTypeVariables`` extension has a restriction that type variables in patterns can only refer to type variables, not 13 | full types. This proposal lifts this restriction. 14 | 15 | 16 | Motivation 17 | ------------ 18 | 19 | ``-XScopedTypeVariables`` allows us to write code like this:: 20 | 21 | f :: Maybe a -> Int 22 | f (Just (x :: b)) = 23 | 24 | This is clearly fine. ``b`` scopes over ````. The variable `a` is not in scope at all (no explicit forall). We can also write:: 25 | 26 | f :: forall a. Maybe a -> Int 27 | f (Just (x :: b)) = 28 | 29 | Now both ``a`` and ``b`` are in scope in ````, as aliases. Great. So if that all works, isn't it strange to reject this:: 30 | 31 | f :: Maybe Int -> Int 32 | f (Just (x :: a)) = 33 | 34 | If this was allowed ``a`` would have to be an alias for ``Int``. Currently that is not allowed: a lexically scoped type variable can only be bound to a type *variable*. The whole and sole point of the proposal is to lift that restriction. 35 | 36 | The restriction is documented as follows: 37 | 38 | When a pattern type signature binds a type variable in this way, GHC insists that the type variable is bound to a rigid, or fully-known, type variable. This means that any user-written type signature always stands for a completely known type. 39 | 40 | Simon explains the motivation behind this restriction: 41 | 42 | I agree this is a questionable choice. At the time I was worried that it'd be confusing to have a type variable that was just an alias for ``Int``; that is not a type variable at all. But in these days of GADTs and type equalities we are all used to that. We'd make a different choice today. 43 | 44 | Let’s do this! 45 | 46 | 47 | One reason for making the change is that it's not really clear what being "bound to a type variable" means in the presence of type equalities. For example:: 48 | 49 | f1 :: (a ~ Int) => Maybe a -> Int 50 | f1 (Just (x :: b)) = 51 | 52 | f2 :: (a ~ Int) => Maybe Int -> Int 53 | f2 (Just (x :: a)) = 54 | 55 | Which of these should be accepted under the current rules? (SPJ says: “I don't even know; I'd have to try it.”) An advantage of the proposal is that such questions become irrelevant. 56 | 57 | Here are more type-checking puzzles. Can you tell which lines of ``foo`` typecheck:: 58 | 59 | data P a = P 60 | data T1 a where 61 | MkT1 :: forall a. P a -> T1 a 62 | MkT2 :: forall a. P a -> T1 (a,a) 63 | MkT3 :: forall a b. b ~ Int => P a -> P b -> T1 a 64 | MkT4 :: forall a b. P a -> P b -> T1 a 65 | MkT5 :: forall a b c. b ~ c => P a -> P b -> P c -> T1 a 66 | 67 | foo :: Int -> T1 (Int, Int) -> () 68 | foo 1 (MkT1 (P::P (Int,Int))) = () 69 | foo 2 (MkT1 (P::P (Int,x))) = (() :: x ~ Int => ()) 70 | foo 3 (MkT1 (P::P x)) = (() :: x ~ (Int,Int) => ()) 71 | foo 4 (MkT2 (P::P x)) = (() :: x ~ Int => ()) 72 | foo 5 (MkT3 P (P::P Int)) = () 73 | foo 6 (MkT4 P (P::P b)) = () 74 | foo 7 (MkT5 P (P::P b) (P::P b)) = () 75 | 76 | All lines but line 2 and 3 typecheck, but arguably all could. 77 | 78 | 79 | Another motivation for this proposal is to use ``ScopedTypeVariables`` as abbreviations for long types:: 80 | 81 | f :: ReallyReallyReallyReallyLongTypeName -> T 82 | f (x :: a) = … (read "" :: a) … 83 | -- Instead of f x = … (read "" :: ReallyReallyReallyReallyLongTypeName) … 84 | 85 | 86 | Proposed Change Specification 87 | ----------------------------- 88 | The sentence 89 | 90 | When a pattern type signature binds a type variable in this way, GHC insists that the type variable is bound to a rigid, or fully-known, type variable. This means that any user-written type signature always stands for a completely known type. 91 | 92 | in the documentation for ``ScopedTypeVariables`` is removed. 93 | 94 | No separate pragma is needed for this behaviour, as we are expanding the set of programs accepted by ``ScopedTypeVariables``, but do not change any behaviour with regard to Haskell2010. 95 | 96 | Effect and Interactions 97 | ----------------------- 98 | With the restriction lifted, all lines of the function above typecheck. 99 | 100 | Proposal `#126 `_ has the same restriction for type applications in patterns. If we adopt this proposal, then the restriction 101 | ought to also be lifted for that feature. 102 | 103 | At the moment, a type variable may occur multiple times in multiple pattern signatures in the same pattern. These do not shadow each other, but rather refer to the same type. For example:: 104 | 105 | foo1 :: Int -> Bool -> () 106 | foo1 (_ :: a) (_ :: a) = () -- Type error, because a can not be both int and bool 107 | 108 | foo2 :: Int -> Int -> () 109 | foo2 (_ :: a) (_ :: a) = () -- Ok, binds a to Int 110 | 111 | This behaviour is unchanged by the current proposal. 112 | 113 | The paper `Type variables in patterns `_ (Haskell'18) has typing rules that describe this the proposed behaviour. 114 | 115 | Costs and Drawbacks 116 | ------------------- 117 | Development is small; there is a working prototype in ``wip/T15050`` – after all, we are removing a check! The code that implements this check (which is spread in many places) unfortunately cannot be just removed, as the restriction still applies to kind variables in data type definitions. 118 | 119 | Alternatives 120 | ------------ 121 | If scoped type variables bind only variables, then we should rename ``ScopedTypeVariables`` to ``ScopedTypeVariablesVariables``. 122 | 123 | Doing nothing is an option. 124 | 125 | Unresolved questions 126 | -------------------- 127 | none yet 128 | 129 | Implementation Plan 130 | ------------------- 131 | Brush up ``wip/T15050`` and be done with. 132 | -------------------------------------------------------------------------------- /proposals/0134-deprecating-exports-proposal.rst: -------------------------------------------------------------------------------- 1 | Deprecating Exports 2 | =================== 3 | 4 | .. author:: Alanas Plascinskas 5 | .. date-accepted:: 2018-07-14 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/-/issues/4879 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | This is my GSoC 2018 project for Haskell.org 13 | 14 | The project should be helpful with easing the transition between different versions of code. 15 | This will be achieved by adding a support for a new deprecation pragma, which will allow the library writers to 16 | easily specify, which exports from a module are to be deprecated. 17 | 18 | Motivation 19 | ------------ 20 | As described in the ticket https://gitlab.haskell.org/ghc/ghc/issues/4879 there is sometimes a need to deprecate certain exports from a module. 21 | 22 | Proposed Change Specification 23 | ----------------------------- 24 | The changes proposed are based on the first design option from the ticket https://gitlab.haskell.org/ghc/ghc/issues/4879 25 | 26 | The syntax would be as follows: 27 | 28 | :: 29 | 30 | module Data.List 31 | ( ... 32 | {-# DEPRECATED "Exported from Data.String instead" #-} 33 | lines, 34 | ...t 35 | ) where 36 | ... 37 | 38 | The deprecation pragma would have an effect on an export that immediately follows it, only top level exports would be considered. 39 | 40 | The semantics are also described in the aforementioned ticket as follows: 41 | 42 | You would get a deprecation warning: 43 | 44 | * If you explicitly import a deprecated export: :: 45 | 46 | import Data.List (lines) 47 | * If you refer to the deprecated export, when fully importing a module: :: 48 | 49 | import Data.List 50 | foo = lines 51 | * If you import the same symbol from different modules and only some of them are deprecated exports then referring to the symbol won't give a deprecation warning. For example the following should not give deprecation warnings: :: 52 | 53 | import Data.List 54 | import Data.String 55 | foo = lines 56 | 57 | * However, in the above example, you would get a deprecation warning if you were to refer to the `lines` symbol by name :: 58 | 59 | foo = Data.String.lines 60 | 61 | * It is also important that the warning is not triggered whenever a name is used within a hiding clause, i.e.: :: 62 | 63 | module A ( {-# DEPRECATED "blah" #-} x ) where { x = True } 64 | module B where { import A hiding (x) } 65 | 66 | * A symbol exported by a module is deprecated if all export specifiers for that symbol have a DEPRECATED pragma. It is an error if a symbol is exported multiple times with DEPRECATED pragmas where the deprecation messages differ :: 67 | 68 | -- only T(C) is deprecated 69 | module M 70 | ( {-# DEPRECATED "don't use the constructor" #-} T(C) 71 | , T(D) -- or T, pattern D 72 | ) where 73 | 74 | data T = C ... 75 | pattern D ... 76 | 77 | -- T is deprecated 78 | module M 79 | ( {-# DEPRECATED "don't use the constructor" #-} T(C) 80 | , {-# DEPRECATED "don't use the constructor" #-} T(D) -- or T, pattern D 81 | ) where 82 | 83 | data T = C ... 84 | pattern D ... 85 | 86 | -- error 87 | module M 88 | ( {-# DEPRECATED "message1" #-} T(C) 89 | , {-# DEPRECATED "message2" #-} T(D) -- or T, pattern D 90 | ) where 91 | 92 | data T = C ... 93 | pattern D ... 94 | 95 | 96 | Effect and Interactions 97 | ----------------------- 98 | If implemented correctly, this should not cause any side-effects as the GHC could only display warning messages as a result of the pragma. 99 | All the other behaviour is expected to remain the same. 100 | 101 | 102 | Costs and Drawbacks 103 | ------------------- 104 | The mentors expect that I would be able to finish the project in 6 weeks. 105 | Unless the unforeseen occurs, I think this is a reasonable estimate and I intend to do my best to stick to this schedule. 106 | 107 | Alternatives 108 | ------------ 109 | As far as I know there are no real alternatives to this feature. 110 | 111 | Right now you can only specify that an export from a module is deprecated in a comment, however, the GHC would not bring that up during compile time. 112 | You can also remove the export altogether but the whole point of deprecation warning is to still allow the users to use the method before it is finally removed. 113 | 114 | 115 | Unresolved questions 116 | -------------------- 117 | UPDATE: The proposed design now does not have an export identifier and so the question below is resolved. 118 | 119 | There are 2 different proposed designs: 120 | 121 | 1 :: 122 | 123 | module Data.List 124 | ( ... 125 | {-# DEPRECATE lines "Exported from Data.String instead" #-} 126 | , lines 127 | ... 128 | ) where 129 | ... 130 | 131 | 2 :: 132 | 133 | {-# DEPRECATE_EXPORT lines "Exported from Data.String instead" #-} 134 | 135 | 136 | I am leaning towards the first one as it readily shows next to an export that it is being deprecated but I am very open to any discussion regarding this. 137 | 138 | 139 | Implementation Plan 140 | ------------------- 141 | I would aim to implement the proposed changes as part of my GSoC 2018 commitment. 142 | To achieve this, I will maintain regular communications with my mentors Matthew Pickering and Erik de Castro Lopo and the broader GHC developer community. 143 | -------------------------------------------------------------------------------- /proposals/0158-record-set-field.rst: -------------------------------------------------------------------------------- 1 | Add ``setField`` to ``HasField`` 2 | ================================ 3 | 4 | .. author:: Neil Mitchell 5 | .. date-accepted:: 2019-01-22 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/16232 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | This is a proposal to adjust the built-in typeclass ``HasField``, removing ``getField`` 13 | and adding ``hasField`` (which is powerful enough to get, set and modify a field). 14 | The result would allow type-based resolution of field names in functions that update 15 | records. It *does not* introduce any new extensions. 16 | 17 | Motivation 18 | ---------- 19 | 20 | A serious limitation of the Haskell record system is the inability to 21 | overload field names in record types: for example, if the data types 22 | 23 | .. code-block:: haskell 24 | 25 | data Person = Person { personId :: Int, name :: String } 26 | data Address = Address { personId :: Int, address :: String } 27 | 28 | are in scope in the same module, there is no way to determine which 29 | type an occurrence of the ``personId`` record selector refers to. 30 | The ``HasField`` extension defined in the already-implemented 31 | `Overloaded Record Fields proposal `_ 32 | introduced ``HasField``, to allow type-based resolution of field names and 33 | polymorphism over record selectors. The class ``HasField`` is currently defined as: 34 | 35 | .. code-block:: haskell 36 | 37 | -- | Constraint representing the fact that the field @x@ belongs to 38 | -- the record type @r@ and has field type @a@. 39 | class HasField (x :: k) r a | x r -> a where 40 | getField :: r -> a 41 | 42 | While this class provides a way to get a field, it provides no way to set a field. 43 | To quote the previous proposal: 44 | 45 | In the interests of simplicity, this proposal does not include a class 46 | to provide polymorphism over record updates 47 | 48 | Such a proposal to deal with record updates would clearly be desirable. 49 | 50 | Proposed Change Specification 51 | ----------------------------- 52 | 53 | We propose to adjust ``HasField`` in ``GHC.Records`` to become: 54 | 55 | .. code-block:: haskell 56 | 57 | -- | Constraint representing the fact that the field @x@ can be get and set on 58 | -- the record type @r@ and has field type @a@. This constraint will be solved 59 | -- automatically, but manual instances may be provided as well. 60 | -- 61 | -- The function should satisfy the invariant: 62 | -- 63 | -- > uncurry ($) (hasField @x r) == r 64 | class HasField x r a | x r -> a where 65 | -- | Function to get and set a field in a record. 66 | hasField :: r -> (a -> r, a) 67 | 68 | We propose to have GHC automatically solve new ``HasField`` constraints the same 69 | way it does for the existing ``HasField`` constraints. 70 | 71 | To enhance reverse compatibility and make it easier to use the ``hasField`` function, 72 | we propose also adding to ``GHC.Records``: 73 | 74 | .. code-block:: haskell 75 | 76 | getField :: forall x r a . HasField x r a => r -> a 77 | getField = snd . hasField @x 78 | 79 | setField :: forall x r a . HasField x r a => r -> a -> r 80 | setField = fst . hasField @x 81 | 82 | This proposal *does not* change how record updates are desugared. 83 | 84 | Effect and Interactions 85 | ----------------------- 86 | 87 | Using ``hasField`` it is possible to write a function: 88 | 89 | .. code-block:: haskell 90 | 91 | mkLens :: forall x r a . HasField x r a => Lens' r a 92 | mkLens f r = wrap <$> f v 93 | where (wrap, v) = hasField @x r 94 | 95 | And thus allow generating lenses from the field classes. The function 96 | ``setField`` is also useful in its own right, complementing the existing ``getField`` 97 | method and providing the ability to modify records by field name. 98 | 99 | Costs and Drawbacks 100 | ------------------- 101 | 102 | More code in the compiler. 103 | 104 | Alternatives 105 | ------------ 106 | 107 | 108 | Separate ``getField`` and ``setField`` methods 109 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 110 | 111 | An alternative is to provide two separate methods, rather than the combined ``hasField``. 112 | The separate methods are both simpler, but to implement any fields that perform computation 113 | (e.g. delving into a ``Map``) would require performing that computation twice in a field 114 | modification. By combining the two functions that extra cost can be eliminated. 115 | 116 | Separate methods would also avoid breaking compatibility for people who have already defined 117 | ``HasField``. However, a search of Hackage has not identified anyone defining ``HasField``, 118 | so the breakage is minor. 119 | 120 | Polymorphic updates 121 | ~~~~~~~~~~~~~~~~~~~ 122 | 123 | A *type-changing update* is one where the type ``r`` is higher-kinded and the field 124 | ``x`` is the only member of that type. As an example, given a value of type ``(Int, Bool)``, 125 | the selector pointing to the first component, and a new value of type ``Double`` we can 126 | produce ``(Double, Bool)``. The design space for type-changing updates is large, and almost 127 | certainly requires additional complexity. In contrast, the design space for type-preserving 128 | updates is small and it can be easily incorporated into the existing design. The addition 129 | of type-preserving updates in no way constrains the design space for future type-changing 130 | updates, but is useful in its own right. 131 | 132 | Read-only fields 133 | ~~~~~~~~~~~~~~~~ 134 | 135 | By splitting the type class we could support read-only fields. However, read-only fields 136 | are essentially just functions, and we already have good support for functions throughout 137 | Haskell. In addition, it would likely be necessary to have a decision procedure for whether 138 | a field was read-only, which would quickly become unweildy. 139 | 140 | Unresolved Questions 141 | -------------------- 142 | 143 | None. 144 | 145 | Implementation Plan 146 | ------------------- 147 | 148 | Adam Gundry has offered to implement this feature. 149 | -------------------------------------------------------------------------------- /proposals/0163-stable-names.rst: -------------------------------------------------------------------------------- 1 | Remove an undocumented `StableName` guarantee 2 | ============================================= 3 | 4 | .. author:: David Feuer 5 | .. date-accepted:: 2018-09-30 6 | .. ticket-url:: 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The ``hashStableName`` function in ``System.Mem.Weak`` is explicitly 13 | documented as not being injective. However, under certain circumstances 14 | users actually *can* rely on it being injective. I propose to remove 15 | this de facto guarantee. 16 | 17 | Motivation 18 | ------------ 19 | 20 | At present, stable names are implemented using two tables: a hash table and a 21 | "stable name table". The stable name table uses three words per stable name, 22 | and we need a non-trivial amount of code to keep the hash table, the stable 23 | name table, and the actual ``StableName#`` objects synced up, particularly 24 | during garbage collection. I realized yesterday that we should actually be able 25 | to implement all the *documented* guarantees of ``StableName``\s without using 26 | a stable name table at all. We can, I believe, get away with just one hash 27 | table per GC generation and a radically simpler garbage collection strategy. 28 | 29 | What the stable name table really lets us do is make an *undocumented* 30 | guarantee: if ``sn1`` and ``sn2`` are stable names, ``sn1`` was alive 31 | when ``sn2`` was created by ``makeStableName``, and 32 | ``hashStableName sn1 = hashStableName sn2``, then ``sn1 = sn2``. 33 | 34 | Proposed Change Specification 35 | ----------------------------- 36 | 37 | Reimplement ``StableName``\s in a simpler, more efficient way that 38 | does not make the described de facto guarantee. Collisions will remain 39 | quite rare (and will almost never happen on 64-bit architectures), 40 | but there will no longer be any way to guarantee that they absolutely 41 | will not occur. 42 | 43 | Effect and Interactions 44 | ----------------------- 45 | 46 | I don't foresee any significant interactions. 47 | 48 | Costs and Drawbacks 49 | ------------------- 50 | 51 | * Any code relying on the de facto guarantee will break, probably 52 | silently, and probably intermittently. 53 | 54 | * Someone will actually have to write the simplified implementation. 55 | If I understand what's going on correctly, this shouldn't take more 56 | than a day or so for someone who's familiar with the GHC garbage 57 | collector, or somewhat longer for someone who's not. 58 | 59 | Alternatives 60 | ------------ 61 | 62 | The obvious alternative is to *document* the de facto guarantee. This would 63 | allow some (very carefully written) code to be simpler and/or more efficient. 64 | For example, we could implement a map from stable names to values like so: :: 65 | 66 | touchStableName :: StableName a -> IO () 67 | touchStableName (StableName sn) = 68 | IO $ \s -> (# touch# sn s, () #) 69 | 70 | newtype SNMap k v = SNMap (IntMap (StableName k, v)) 71 | 72 | empty :: SNMap k v 73 | empty = SNMap (IM.empty) 74 | 75 | insert :: k -> v -> SNMap k v -> IO (SNMap k v) 76 | insert k v (SNMap im) = do 77 | snk <- makeStableName k 78 | pure $! SNMap (IM.insert (hashStableName snk) (snk, v) im) 79 | 80 | lookup :: k -> SNMap k v -> IO (Maybe v) 81 | lookup k (SNMap im) = do 82 | snk <- makeStableName k 83 | case lookup (hashStableName snk) im of 84 | Nothing -> pure Nothing 85 | Just (sn, v) -> do 86 | touchStableName sn 87 | pure (Just v) 88 | 89 | We don't need to worry about hash collisions on lookup because 90 | we ensure (using ``touchStableName``) that ``sn`` was alive when ``snk`` 91 | was created, and therefore the equality of their hashes implies 92 | their equality. 93 | 94 | There is a clear trade-off here between complexity of code using 95 | stable names and complexity of the code implementing them. There's 96 | also a balance in where we pay performance prices. At the moment, 97 | we're getting the worst of both worlds, paying the price to implement 98 | conditional injectivity but not letting users reap any benefits. 99 | I think we should definitely do one or the other. 100 | 101 | Unresolved Questions 102 | -------------------- 103 | 104 | Is anyone currently relying on the de facto guarantee? 105 | 106 | Implementation Plan 107 | ------------------- 108 | I'd be happy to work on it myself, but I'd need some help from the 109 | GHC garbage collection experts. 110 | -------------------------------------------------------------------------------- /proposals/0166-ghci-instances.rst: -------------------------------------------------------------------------------- 1 | List instances for a type in GHCi 2 | ============== 3 | 4 | .. author:: Xavier Denis 5 | .. date-accepted:: 2018-11-05 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/15610 7 | .. implemented:: 8.10 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_ 10 | .. contents:: 11 | 12 | 13 | There is currently no mechanism to get the instances for a specific type in GHCi, `:info` command allow specifying more than a top-level constructor. This proposal suggests a new GHCi command that would allow programmers to query GHC for valid instances matching a type. 14 | 15 | Motivation 16 | ------------ 17 | 18 | Typeclass resolution and deriviation are integral parts of modern Haskell. Unfortunately, the compiler doesn't volunteer a lot of information on them during development. Figuring out whether a type has a specific instance usually requires you to work backwards: starting from the typeclass and going through every instance in Haddock, recursively, to figure out if your type satisfies it. This experience isn't optimal and can get annoying for large or nested types and classes. 19 | 20 | This is exactly the kind of task that the compiler could help us with though. Since it already has all the visible instances for a given piece of code loaded, we could just ask it to list all instances that a type matches! This proposal suggests adding a new command and related machinery to GHCi to acomplish this. An example of this command's possible execution is shown below: 21 | 22 | .. code-block:: none 23 | 24 | >> import Data.Functor.Sum (Sum) 25 | >> 26 | >> :instances Sum [] [] 27 | Eq a => Eq (Sum [] [] a) 28 | Ord a => Ord (Sum [] [] a) 29 | Show a => Show (Sum [] [] a) 30 | Read a => Read (Sum [] [] a) 31 | Functor (Sum [] []) 32 | Foldable (Sum [] []) 33 | Eq1 (Sum [] []) 34 | Ord1 (Sum [] []) 35 | Show1 (Sum [] []) 36 | Read1 (Sum [] []) 37 | FunctorWithIndex (Either Int Int) (Sum [] []) 38 | FoldableWithIndex (Either Int Int) (Sum [] []) 39 | TraversableWithIndex (Either Int Int) (Sum [] []) 40 | 41 | It would provide a new tool for Haskell developers, both new and experienced that helps during during development and debugging. It allows a new way of talking with our beloved compiler and to better understand how it thinks. 42 | 43 | Proposed Change Specification 44 | ----------------------------- 45 | 46 | This proposal adds a new command to GHCi called ``:instances`` which provides a listing of all valid instances for a given type. 47 | 48 | Syntax 49 | ~~~~~~ 50 | 51 | Valid queries to ``instances`` are types, if anything other than a type is provided as an argument, the command will return an error explaining the intended usage. The command interprets everything after ``instances`` as a single type, this means there is no way to specify multiple types to lookup instances of MPTCs. Holes can be used to represent free variables in the argument type, for example: ``Either _ _``. To express relations between multiple holes, named holes can be used, for example:: ``Either _a _a``. 52 | 53 | Execution 54 | ~~~~~~~~~ 55 | 56 | Provided with a valid type, ``instances`` will attempt to match it against the heads of all visible class instances and reduce constraints until only those mentioning holes in the type remain. The output will consist of a formatted listing of all matching instances that satisfy the stated condition on constraints. Each instance should be simplified as much as possible, meaning that if an instance: ``(c ~ Bool) => C c`` were found it would be presented as ``C Bool``. 57 | 58 | 59 | Effect and Interactions 60 | ----------------------- 61 | 62 | This new command gives programmers the ability to see every possible instance for a type that the compiler sees. This is useful both for beggining and `advanced `_ haskellers who are exploring types and what they can do with them. 63 | 64 | When combined with recent extensions like ``GeneralizedNewtypeDeriving`` and ``DerivingVia``, a type can 'steal' many instances from other structurally identical ones but finding those instances is currently a tedious manual process. 65 | 66 | This also provides a way for beginners to see what's possible with the types given to them. Instead of having to browse Haddocks and stumble on instances for their type, GHC can simply provide all that information on the spot! 67 | 68 | Since this is simply a GHCi command, there will be no interaction with the language itself. 69 | 70 | Costs and Drawbacks 71 | ------------------- 72 | 73 | The primary costs for this feature are implementation time. Because it is a GHCi command, it won't have any backwards compatibility or performance issues. It should actually help make Haskell a little more accessible to beginners as well, giving a better view on what GHC sees as possible instances for their types. 74 | 75 | Alternatives 76 | ------------ 77 | 78 | Currently GHCi has an ``:info`` command which offers some information on instances. However, ``:info`` only works on single words, which means that ``:info Either String Int`` will return results for ``Either``, ``String``, and ``Int`` separately. This makes it a partial replacement at best for the ``:instances`` command. 79 | 80 | Examples 81 | -------- 82 | 83 | 84 | .. code-block: none 85 | 86 | >> :instances Sum f f 87 | Functor f => Functor (Sum f f) 88 | Foldable f => Foldable (Sum f f) .. 89 | 90 | Basic instance lookup: 91 | 92 | .. code-block: none 93 | >> :instances [_] 94 | 95 | Show _ => Show [_] 96 | Eq _ => Eq [_] 97 | .... 98 | 99 | Often when dealing with monad stacks, it can be useful to figure out exactly which instances are available for a given type: 100 | 101 | .. code-block: none 102 | >> :instances StateT _s (ReaderT _r IO) 103 | MonadIO (StateT _s (ReaderT _r IO)) 104 | Functor (StateT _s (ReaderT _r IO)) 105 | MonadState (StateT _s (ReaderT _r IO)) 106 | MonadReader (StateT _s (ReaderT _r IO)) 107 | ... 108 | 109 | 110 | Unresolved Questions 111 | -------------------- 112 | 113 | 114 | Future Work 115 | ----------- 116 | 117 | The original `ticket `_ also suggests some further work. There are several improvements that could be proposed. These are meant as ideas that could be fleshed out in a future proposal. 118 | 119 | Negative Results 120 | ~~~~~~~~~~~~~~~~ 121 | 122 | A second command ``:noinstance`` would output a list of the unsatisfied constraints that prevent an instance from being found for a specific type. 123 | 124 | Multi-Parameter Type Classes 125 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 126 | 127 | Adding support for searching for multi-parameter type classes that include several specified types could be useful as well. It's unclear how to actually dilineate the multiple types that need to be provided. 128 | 129 | Trace Info 130 | ~~~~~~~~~~ 131 | 132 | We could annotate the specific location that each instance was provided from. 133 | 134 | .. code-block:: none 135 | >> :instances Sum [] [] 136 | .. 137 | Functor (Sum [] []) -- (Functor f, Functor g) => Functor (Sum f g) -- Defined in ‘Data.Functor.Sum’ 138 | .. 139 | 140 | Implementation Plan 141 | ------------------- 142 | 143 | If accepted, I, `@xldenis `_ intend to implement this feature. 144 | -------------------------------------------------------------------------------- /proposals/0168-fail-rebindable-with-overloaded-strings.rst: -------------------------------------------------------------------------------- 1 | Make rebindable ``fail`` work with overloaded strings 2 | ===================================================== 3 | 4 | .. author:: Shayne Fletcher 5 | .. date-accepted:: 2018-10-21 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/15645 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | We propose that string literals generated by GHC and passed to user 13 | defined functions should have ``fromString`` applied. The only 14 | instance of such GHC generated strings we are aware of is via 15 | ``fail``, so we propose to fix that case. Concretely, for monadic 16 | pattern match failures in the presence of the extensions 17 | ``RebindableSyntax`` and ``OverloadedStrings``, we desugar to ``fail 18 | (fromString "error")`` instead of ``fail "error"`` . 19 | 20 | Motivation 21 | ---------- 22 | We might expect the following program to work: 23 | 24 | .. code-block:: haskell 25 | 26 | {-# LANGUAGE RebindableSyntax #-} 27 | {-# LANGUAGE OverloadedStrings #-} 28 | 29 | module Fail where 30 | 31 | import Prelude hiding (fail) 32 | 33 | foo x = do 34 | Just y <- x 35 | return y 36 | 37 | newtype Text = Text String 38 | 39 | fail :: Text -> a 40 | fail (Text x) = error x 41 | 42 | fromString :: String -> Text 43 | fromString = Text 44 | 45 | The intent is that the defined ``fail`` should take an argument of 46 | type ``Text`` which is obtained by implicit conversion from 47 | ``String``. 48 | 49 | However, it fails with, 50 | 51 | :: 52 | 53 | Fail.hs:8:5-15: error: 54 | * Couldn't match expected type `[Char]' with actual type `Text' 55 | * In a stmt of a 'do' block: Just y <- x 56 | In the expression: 57 | do Just y <- x 58 | return y 59 | In an equation for `foo': 60 | foo x 61 | = do Just y <- x 62 | return y 63 | | 64 | 8 | Just y <- x 65 | | ^^^^^^^^^^^ 66 | 67 | Proposed Change Specification 68 | ----------------------------- 69 | We propose that monadic pattern match failure in the presence of 70 | ``RebindableSyntax`` and ``OverloadedStrings`` desugars to ``fail 71 | (fromString "error")`` instead of ``fail "error"``. 72 | 73 | Effects and Interactions 74 | ------------------------ 75 | With this modification, the example program from the “Motivation” 76 | section will type-check. It would be possible for a 77 | ``Prelude``-replacement to eliminate ``String`` more completely, 78 | without having to retain it as the input type to ``fail``. 79 | 80 | We view this change primarily as a bug fix, which simplifies an 81 | unexpected corner. This proposal originally started out as 82 | https://gitlab.haskell.org/ghc/ghc/issues/15645. 83 | 84 | Costs and Drawbacks 85 | ------------------- 86 | There may be a small number of libraries that fail to type-check, but 87 | any that have simply enabled the two extensions will continue to work, 88 | as ``fromString`` has an instance for ``String``. In all likelihood, 89 | these are the libraries that have already tried to eliminate 90 | ``String``, so are most likely to benefit from the change. 91 | 92 | Alternatives 93 | ------------ 94 | One can work around the problem by requiring the user to write ``fail 95 | = myFail . fromString``, but that requires both ``fail`` and 96 | ``myFail`` to be in scope, and the name ``fail`` cannot be reused for 97 | the failure function in the monad typeclass. 98 | 99 | Unresolved Questions 100 | -------------------- 101 | Should ``fromString`` be injected only when both ``OverloadedStrings`` 102 | and ``RebindableSyntax`` are enabled or just ``OverloadedStrings``? We 103 | suggest only when both as, when ``RebindableSyntax`` is not enabled, 104 | the operation ``fail . fromString`` is equivalent to ``fail``. 105 | 106 | Implementation Plan 107 | ------------------- 108 | We (the proposal authors) will implement the change. Our plan is to 109 | modify ``getFailFunction`` and ``failFunction`` in ``RnExpr.hs`` so 110 | that if the ``RebindableSyntax`` and ``OverloadedStrings`` language 111 | extensions are enabled, then ``fail_op`` becomes ``fail . fromString`` 112 | rather than just ``fail``. 113 | -------------------------------------------------------------------------------- /proposals/0170-unrestricted-overloadedlabels.rst: -------------------------------------------------------------------------------- 1 | Unrestricted Overloaded Labels 2 | ============================== 3 | 4 | .. author:: howtonotwin 5 | .. date-accepted:: 2018-11-05 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/11671 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_ 10 | .. contents:: 11 | 12 | ``OverloadedLabels`` are a useful feature, but they have somewhat unexpected syntax restrictions on what is a valid label. This proposal exists to alleviate this. 13 | 14 | Motivation 15 | ------------ 16 | ``#foo`` is a valid expression with ``-XOverloadedLabels``, but ``#Foo`` is not. This is somewhat surprising, as ``#foo`` is only syntax for ``fromLabel @"foo"``. This can mean anything, so it doesn't make sense to enforce a case distinction as done for constructors and functions. Similarly, ``#3`` is not valid, nor is any other number. There isn't much reason against this, either. 17 | 18 | There are real world cases in the ticket, usually because libraries want to define the syntax ``#Foo`` to do something constructor related. 19 | 20 | Proposed Change Specification 21 | ----------------------------- 22 | Immediately following a ``#``, with no intervening whitespace, allow any nonempty string of characters that is composed out of the same characters that make up variable names and numeric literals. Also, allow strings of characters that look like string literals. In the language of the Report, labels are defined by: 23 | 24 | | *labelChar* → *small* | *large* | *digit* | ``'`` | ``.`` 25 | | *label* → ``#``\ (*string* | *labelChar* {*labelChar*}) 26 | 27 | A "quoted" label ``#``\ ⟨string⟩ translates to ``fromLabel @``\ ⟨string⟩, and a "bare" label ``#``\ ⟨labelChars⟩ translates to ``fromLabel @"``\ ⟨labelChars⟩\ ``"``. This is a table of some example labels and their translations. 28 | 29 | ========================== ==================================== ============ 30 | Label syntax Translation Works today? 31 | ========================== ==================================== ============ 32 | ``#a`` ``fromLabel @"a"`` Yes 33 | ``#number17`` ``fromLabel @"number17"`` Yes 34 | ``#do`` ``fromLabel @"do"`` Yes 35 | ``#type`` ``fromLabel @"type"`` Yes 36 | ``#Foo`` ``fromLabel @"Foo"`` No 37 | ``#"Foo"`` ``fromLabel @"Foo"`` No 38 | ``#3`` ``fromLabel @"3"`` No 39 | ``#"3"`` ``fromLabel @"3"`` No 40 | ``#199.4`` ``fromLabel @"199.4"`` No 41 | ``#17a23b`` ``fromLabel @"17a23b"`` No 42 | ``#"The quick brown fox"`` ``fromLabel @"The quick brown fox"`` No 43 | ``#f'a'`` ``fromLabel @"f'a'"`` Yes 44 | ``#'a'`` ``fromLabel @"'a'"`` No 45 | ``#":"`` ``fromLabel @":"`` No 46 | ``#'`` ``fromLabel @"'"`` No 47 | ``#"\""`` ``fromLabel @"\""`` No 48 | ========================== ==================================== ============ 49 | 50 | Effect and Interactions 51 | ----------------------- 52 | ``(#)`` is a valid name for an operator. The current ``-XOverloadedLabels`` steals syntax, as ``a#b`` means ``(#) a b`` without it and ``a (fromLabel @"b")`` with it (the difference is even more catastrophic for e.g. ``a#do ...``). This proposal steals more syntax in the same manner. E.g. the meanings of ``a#3``, ``a#"foo"``, ``a#'b'``, and ``a#Foo`` all change. 53 | 54 | Costs and Drawbacks 55 | ------------------- 56 | The syntax stealing above is one drawback. There is also the somewhat confusing possibility of things like ``#'a'``. The actual implementation should be simple and easy to maintain. 57 | 58 | Alternatives 59 | ------------ 60 | Do nothing and just let libraries keep using tricks like ``#_Foo``. 61 | 62 | Unresolved questions 63 | -------------------- 64 | None. 65 | 66 | Implementation Plan 67 | ------------------- 68 | TBA 69 | -------------------------------------------------------------------------------- /proposals/0173-dot-type-operator.rst: -------------------------------------------------------------------------------- 1 | The dot type operator 2 | ===================== 3 | 4 | .. author:: Vladislav Zavialov 5 | .. date-accepted:: 2018-11-05 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/merge_requests/363 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The ``TypeOperators`` language extension allows using symbols in type names, 13 | similarly to operators in terms. However, some operator names that are valid in 14 | terms are not valid in types, including the dot operator ``(.)`` commonly used 15 | to denote function composition. We propose to lift this restriction. 16 | 17 | Motivation 18 | ------------ 19 | 20 | At the moment, we cannot define function composition at type level:: 21 | 22 | ghci> type (f . g) x = f (g x) 23 | 24 | :1:9: error: 25 | Illegal symbol '.' in type 26 | Perhaps you intended to use RankNTypes or a similar language 27 | extension to enable explicit-forall syntax: forall . 28 | 29 | There are two issues with this definition: 30 | 31 | 1. The dot is not a valid type operator. 32 | 2. The type synonyms and type families cannot be partially applied, severely 33 | limiting the usability of type-level function composition. 34 | 35 | In this proposal, we seek to address the first issue. The second issue is out 36 | of scope, but can be addressed with defunctionalization today or by allowing 37 | unsaturated use type functions in the future. 38 | 39 | With a small modification to the Haskell grammar, the following code is 40 | accepted:: 41 | 42 | ghci> :set -XTypeOperators 43 | ghci> type (f . g) x = f (g x) 44 | ghci> Nothing :: (Maybe . Either Int) Bool 45 | Nothing 46 | ghci> Just (Left 5) :: (Maybe . Either Int) Bool 47 | Just (Left 5) 48 | 49 | We can achieve this by changing a single production in ``Parser.y``, namely 50 | ``tyapp``:: 51 | 52 | - | tyvarop { sL1 $1 $ TyElOpr (unLoc $1) } 53 | + | '`' tyvarid '`' { sLL $1 $> $ TyElOpr (unLoc $2) } 54 | + | '.' { sL1 $1 $ TyElOpr (mkUnqual tcClsName (fsLit ".")) } 55 | 56 | Note that the actual implementation will be more complex to provide decent 57 | error messages, keep `annotations 58 | `_ working, etc. 59 | 60 | We can use whitespace to disambiguate between uses of the dot as a type 61 | operator and as a part of a qualified name. The situation is the same as in 62 | terms, demonstrated by this table (courtesy of `@mstksg 63 | `_):: 64 | 65 | foo . bar -- term level: (.) foo bar 66 | -- type level: (.) foo bar (currently disallowed) 67 | 68 | foo.bar -- term level: (.) foo bar 69 | -- type level: (.) foo bar (currently disallowed) 70 | 71 | Foo . Bar -- term level: (.) Foo Bar 72 | -- type level: (.) Foo Bar (currently disallowed) 73 | 74 | Foo.Bar -- term level: Bar imported from module Foo 75 | -- type level: Bar imported from module Foo 76 | 77 | In the ``singletons`` library, there is a `special case 78 | `_ 79 | for promotion of ``(.)`` and ``(!)``:: 80 | 81 | Note [Special cases for (.) and (!)] 82 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | Almost every infix value name can be promoted trivially. For example, (+) 84 | works both at the value- and type-level. The two exceptions to this rule 85 | are (.) and (!), which we promote to the special type names (:.) and (:!), 86 | respectively. This is necessary since one cannot define or apply (.) or 87 | (!) at the type level -- they simply won't parse. Bummer. 88 | 89 | The issue with ``(!)`` has been fixed in the upcoming GHC 8.8, but the problem 90 | of ``(.)`` remains. 91 | 92 | Proposed Change Specification 93 | ----------------------------- 94 | 95 | Allow the use of the ``(.)`` type operator in all places where other type 96 | operators are legal. 97 | 98 | Effect and Interactions 99 | ----------------------- 100 | 101 | Clasess, data types, data families, type synonyms, and type families can now be 102 | given the name ``(.)``. 103 | 104 | There are no known conflicts with other language features despite the use of 105 | the dot in type-level constructs like ``forall . ``. The parser has 106 | enough information to disambiguate in all cases. 107 | 108 | Costs and Drawbacks 109 | ------------------- 110 | 111 | None. 112 | 113 | Alternatives 114 | ------------ 115 | 116 | * Continue to disallow the use of the dot operator in types. 117 | * Find a different use for the dot syntax inconsistent with terms. 118 | 119 | Unresolved Questions 120 | -------------------- 121 | 122 | None. 123 | 124 | Implementation Plan 125 | ------------------- 126 | 127 | I (Vladislav Zavialov) will implement this change. 128 | 129 | -------------------------------------------------------------------------------- /proposals/0174-unpack-pragma-precedence.rst: -------------------------------------------------------------------------------- 1 | Lower precedence for {-# UNPACK #-} 2 | =================================== 3 | 4 | .. author:: Vladislav Zavialov 5 | .. date-accepted:: 2018-10-20 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/14761 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The ``{-# UNPACK #-}`` pragma is not valid inside a type but binds more 13 | tightly than function application. This is suboptimal because it contradicts 14 | user expectations (`#14761 15 | `_) and forces unnecessary 16 | parenthesization of types. We propose to lower the precedence of ``{-# UNPACK 17 | #-}``. 18 | 19 | Motivation 20 | ------------ 21 | 22 | Compare the following declarations:: 23 | 24 | data A = A { a :: {-# UNPACK #-} Maybe Int } 25 | data B = B { b :: {-# UNPACK #-} (Maybe Int) } 26 | 27 | While ``B`` is accepted (without warning when ``-XStrictData`` is on), ``A`` 28 | fails with the following error:: 29 | 30 | :1:21: error: 31 | • Unexpected strictness annotation: {-# UNPACK #-}Mayb 32 | e 33 | • In the type ‘{-# UNPACK #-}Maybe Int’ 34 | In the definition of data constructor ‘A’ 35 | In the data declaration for ‘A’ 36 | 37 | This happens because it is parsed as ``({-# UNPACK #-} Maybe) Int``, but ``{-# 38 | UNPACK #-}`` is only valid at the outer level of a type in a data constructor 39 | field. 40 | 41 | In GADT declarations, a similar issue occurs:: 42 | 43 | data A where A :: {-# UNPACK #-} Maybe Int -> A 44 | data B where B :: {-# UNPACK #-} (Maybe Int) -> B 45 | 46 | Proposed Change Specification 47 | ----------------------------- 48 | 49 | Lower the precedence of ``{-# UNPACK #-}`` and ``{-# NOUNPACK #-}`` so that 50 | they bind as loosely as possible, but tighter than ``(->)``. 51 | 52 | Effect and Interactions 53 | ----------------------- 54 | 55 | The change is conservative: strictly more programs will be accepted. 56 | 57 | Costs and Drawbacks 58 | ------------------- 59 | 60 | None. 61 | 62 | Alternatives 63 | ------------ 64 | 65 | A similar argument can be made for ``!`` and ``~`` when they are used as 66 | strictress/laziness annotations, but Simon Peyton Jones `argues 67 | `_ that it would "look 68 | wrong": 69 | 70 | Both ``{-# UNPACK #-}`` and ``!`` only make sense at the outer level of a type 71 | in a data constructor field. But in GADT-style declarations, they can 72 | appear to be "inside" a type:: 73 | 74 | data T where K :: !(Maybe Int) -> {-# UNPACK #-} !Int -> T 75 | 76 | Somehow ``!`` looks as if it should bind tightly. e.g. ``!Maybe Int -> 77 | T`` looks wrong. But I agree that ``{-# UNPACK #-}`` would be better with 78 | a lower precedence. 79 | 80 | Unresolved Questions 81 | -------------------- 82 | 83 | Should we also lower the precedence of ``!`` and ``~``? 84 | 85 | Implementation Plan 86 | ------------------- 87 | 88 | I (Vladislav Zavialov) will implement this change. Most of the work is already 89 | done in `Phab:D5180 `_. 90 | -------------------------------------------------------------------------------- /proposals/0190-module-qualified-syntax.rst: -------------------------------------------------------------------------------- 1 | Allow ``qualified`` to follow module name 2 | ========================================= 3 | 4 | .. author:: Shayne Fletcher 5 | .. date-accepted:: 2019-05-02 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/merge_requests/853 7 | .. implemented:: 8.10 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | We propose to allow the syntax ``import M qualified`` to solve hanging indents in module import lists. 13 | 14 | Motivation 15 | ---------- 16 | To import a qualified module you must specify ``qualified`` in prepositive position : ``import qualified M``. This often leads to a "hanging indent" (which is automatically inserted by some `autoformatters `_ and `common `_ `in `_ `many `_ `code `_ `bases `_). For example: 17 | 18 | :: 19 | 20 | import qualified A 21 | import B 22 | import C 23 | 24 | We propose to also allow ``qualified`` to appear in postpositive position : ``import M qualified``. In that case, one could write: 25 | 26 | :: 27 | 28 | import A qualified 29 | import B 30 | import C 31 | 32 | While a small change, this annoyance is a significant issue in many large codebases, where programmers are forced to "pick a style" - chosing to add redundant whitespace to have modules align, or to make scanning import lists harder. Additionally, the location of `qualified` makes sorting imports harder. 33 | 34 | Proposed Change Specification 35 | ----------------------------- 36 | A new language extension ``ImportQualifiedPost`` is introduced. When enabled, ``qualified`` will be accepted in postpositive position, by updating the ``importdecl`` production like so: 37 | 38 | :: 39 | 40 | importdecl :: { LImportDecl GhcPs } 41 | : 'import' maybe_src maybe_safe optqualified maybe_pkg modid optqualified maybeas maybeimpspec 42 | 43 | A new warning ``-Wprepositive-qualified-module`` (off by default) will be introduced that warns on prepositive syntax: 44 | 45 | :: 46 | 47 | Preposition.hs:5:8: warning: [-Wprepositive-qualified-module] 48 | Found ‘qualified’ in prepositive position 49 | Suggested fix: place ‘qualified’ after the module name instead. 50 | | 51 | 5 | import qualified Data.List 52 | | ^^^^^^^^^ 53 | 54 | Effect and Interactions 55 | ----------------------- 56 | The proposed change adds the ability to specify a qualified import by placing ``qualified`` either before or after the module name. Under ``ImportQualifiedPost``, ``qualified`` will be permitted in either pre- or post-positive positions (but not both). If in the future we decide to deprecate the pre-positive syntax, we would make an extension flag for that and allow it to be turned off. 57 | 58 | The position of the ``qualified`` does not change the semantics, and is independent from any other import features (e.g. package imports or safe annotations). As an example, both ``import qualified D as E`` and ``import D qualified as E`` are permitted and equivalent. 59 | 60 | There should be no other interactions with any existing language or compiler features. 61 | 62 | Costs and Drawbacks 63 | ------------------- 64 | The implementation of the change is but a few lines (``Parser.y`` for the grammar and ``RdrHsSyn.hs`` for warnings/errors). The increased flexibility comes with no discernible drawbacks. 65 | 66 | Alternatives 67 | ------------ 68 | The alternatives appear to be: 69 | (1) Keep the status-quo and do not allow the alternate syntax; 70 | (2) Mandate the alternative syntax and formulate a migration strategy. 71 | 72 | The second alternative solves the motivating hanging indent issue but in our opinion both alternatives seem needlessly strict when both conventions can be had cheaply with only upside. 73 | 74 | Unresolved Questions 75 | -------------------- 76 | There are no remaining unresolved questions. 77 | 78 | Implementation Plan 79 | ------------------- 80 | If accepted, the proposal authors will implement the change. 81 | -------------------------------------------------------------------------------- /proposals/0193-forall-keyword.rst: -------------------------------------------------------------------------------- 1 | Make ``forall`` a keyword 2 | ========================= 3 | 4 | .. author:: Richard Eisenberg 5 | .. date-accepted:: 2019-02-14 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/merge_requests/363 7 | .. implemented:: 8.8 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | Having accepted proposals for `dependent visible quantification`_ 13 | (`discussion `_) and 14 | for the `dot type operator`_ 15 | (`discussion `_), we now have the potential for 16 | situations where a type can change meaning depending on what extensions are enabled. This is unfortunate. 17 | This proposal suggests that ``forall`` should be considered a keyword in types always, regardless 18 | of extensions. 19 | 20 | .. _`dependent visible quantification`: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0035-forall-arrow.rst 21 | .. _`dot type operator`: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0039-dot-type-operator.rst 22 | 23 | Motivation 24 | ------------ 25 | Consider these type signatures:: 26 | 27 | f1 :: forall a. a -> a 28 | f2 :: forall a -> a -> a 29 | 30 | What do they mean? It depends on what extensions are in force. 31 | 32 | * ``f1`` is rejected in Haskell2010. But with ``-XTypeOperators`` enabled (and 33 | the `dot type operator`_ feature implemented), it means ``((.) (forall a) a) -> a``, 34 | where ``forall`` is an ordinary type variable. With ``-XExplicitForAll`` enabled, 35 | we get quantification over ``a``. Both interpretations are sensible 36 | and potentially well-kinded. 37 | 38 | * ``f2`` is accepted in Haskell2010, with ``forall`` being understood as an ordinary 39 | type variable. But with `dependent visible quantification`_ in effect, that type signature 40 | quantifies over ``a`` and then expects an argument of type ``a``. (The dependent visible 41 | quantification proposal does not say what extension enables the feature. I am assuming it 42 | comes with ``-XExplicitForAll``.) 43 | 44 | What's troublesome here is that a user might write one of these signatures, intending for quantification, 45 | but forgetting to enable ``-XExplicitForAll``. Instead of getting a helpful error message asking that 46 | they enable ``-XExplicitForAll``, they would get obscure type errors. 47 | 48 | Proposed Change Specification 49 | ----------------------------- 50 | The lexeme ``forall`` is understood to be a keyword in types, always. Similarly, the unicode variant 51 | of ``forall`` would be understood as a keyword in types, always. 52 | 53 | Effect and Interactions 54 | ----------------------- 55 | * This proposal would potentially break some existing programs, if any program uses a type variable 56 | spelled ``forall``. These would be easily fixed, simply by using a different type variable name. 57 | This proposal author doubts the existence of any such programs in the wild. 58 | 59 | * There is precedent for this kind of syntax-stealing behavior. 60 | 61 | - Several lexemes are already pseudo-keywords in types. These include ``family`` and ``role``. 62 | With ``-XTypeOperators`` (but no other extensions), one might assume that you could write 63 | ``type family + x = Either family x`` to make ``+`` a synonym for ``Either``. Yet GHC rejects 64 | this because it expects ``type family`` to begin a type family declaration. 65 | 66 | - If you have a term-level function named ``forall``, you cannot write ``RULES`` for it. For example, 67 | if we have ``forall x = x``, you might want ``{-# RULES "forall" forall = id #-}``. Yet GHC 68 | interprets the word ``forall`` as introducing term-level quantified variables in a rewrite rule. 69 | This syntax is not allowed. 70 | 71 | Admittedly, these examples require non-standardized syntax, whereas the current proposal interferes 72 | with the standard. 73 | 74 | * Error messages would improve with this change, as GHC would be able to unambiguously detect when 75 | the user wants quantification. 76 | 77 | * This proposal does *not* interact meaningfully with the ``-XExplicitForAll``. It does *not* turn 78 | the extension on automatically. It simply reserves the lexeme ``forall``. This means that any 79 | program with the lexeme ``forall`` appearing in a type will be in error if ``-XExplicitForAll`` 80 | is not enabled. 81 | 82 | Costs and Drawbacks 83 | ------------------- 84 | * The major drawback is that it moves us further from the standard. However, this particular deviation 85 | seems slight. 86 | 87 | Alternatives 88 | ------------ 89 | * **Do nothing**. The status quo includes no programs that are ambiguous to GHC (or other tooling), because 90 | these tools can always know what extensions are in effect. Yet, programs may be confusing or ambiguous 91 | to poor humans, who might not always know what extensions are in effect. 92 | 93 | * **Hide this feature behind an extension**. We could introduce ``-XKeywordForall`` that enables this new 94 | behavior. In order to satisfy the needs in the Motivation, this extension would have to be enabled by default. 95 | It should also, logically, be disabled by ``-XHaskell2010`` and ``-XHaskell98``. However, it is now 96 | common practice to specify a "default language" in ``.cabal`` files, and ``cabal`` builds files with one 97 | of these extensions specified. So, if we did this, any users compiling via ``cabal`` would not reap the 98 | benefits of the better error messages this proposal would enable. 99 | 100 | * **Make ``forall`` a keyword in all contexts**. Should ``forall`` be a keyword everywhere? This alternative 101 | is more future-compatible with the possibility of dependent types. Yet it would break known programs 102 | (e.g., Idris, which has a function named ``forall``). I'm open to this possibility, but in the end, 103 | I currently think it's better to just do this in types, for now. 104 | 105 | Unresolved Questions 106 | -------------------- 107 | None at this time. 108 | 109 | Implementation Plan 110 | ------------------- 111 | This would likely be implemented alongside the implementations for either `dependent visible quantification`_ 112 | or the `dot type operator`_. 113 | -------------------------------------------------------------------------------- /proposals/0195-code-texp.rst: -------------------------------------------------------------------------------- 1 | Make Q (TExp a) into a newtype 2 | ============== 3 | 4 | 5 | .. author:: Matthew Pickering 6 | .. date-accepted:: 2020-05-26 7 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/16177 8 | .. implemented:: 9.0 9 | .. highlight:: haskell 10 | .. header:: This proposal was `discussed at this pull request `_. 11 | .. contents:: 12 | 13 | I propose to modify the Typed Template Haskell API to make the ``Code`` type 14 | more abstract. In particular we introduce a new data type called ``Code`` which 15 | is abstract such that ``Code m a`` represents an expression of type ``a`` produced 16 | in a monadic context ``m``. The reader should note that this proposal builds on 17 | top of the `overloaded quotations proposal `_ which was 18 | accepted before this proposal. 19 | 20 | The Untyped Template Haskell API is unmodified. This proposal is only about 21 | Typed Template Haskell. 22 | 23 | 24 | Motivation 25 | ------------ 26 | 27 | There are three problems with the current API: 28 | 29 | 1. It is hard to properly write instances for ``Quote m => m (TExp a)`` as the type is the composition 30 | of two type constructors. Doing so in your program involves making your own newtype and 31 | doing a lot of wrapping/unwrapping. 32 | 33 | For example, if I want to create a language which I can either run immediately or 34 | generate code from I could write the following with the new API. :: 35 | 36 | class Lang r where 37 | _int :: Int -> r Int 38 | _if :: r Bool -> r a -> r a -> r a 39 | 40 | instance Lang Identity where 41 | _int = Identity 42 | _if (Identity b) (Identity t) (Identity f) = Identity (if b then t else f) 43 | 44 | instance Quote m => Lang (Code m) where 45 | _int = liftTyped 46 | _if cb ct cf = [|| if $$cb then $$ct else $$cf ||] 47 | 48 | 2. When doing code generation it is common to want to store code fragments in 49 | a map. When doing typed code generation, these code fragments contain a 50 | type index so it is desirable to store them in one of the parameterised 51 | map data types such as ``DMap`` from ``dependent-map`` or ``MapF`` from 52 | ``parameterized-utils``. 53 | 54 | :: 55 | 56 | compiler :: Env -> AST a -> Code Q a 57 | 58 | data AST a where ... 59 | data Ident a = ... 60 | 61 | type Env = MapF Ident (Code Q) 62 | 63 | newtype Code m a = Code (m (TExp a)) 64 | 65 | 66 | In this example, the ``MapF`` maps an ``Ident String`` directly to a ``Code Q String``. 67 | Using one of these map types currently requires creating your own newtype and constantly 68 | wrapping every quotation and unwrapping it when using a splice. Achievable, but 69 | it creates even more syntactic noise than normal metaprogramming. 70 | 71 | 72 | 3. ``m (TExp a)`` is ugly to read and write, understanding ``Code m a`` is 73 | easier. This is a weak reason but one everyone 74 | can surely agree with. 75 | 76 | 77 | Proposed Change Specification 78 | ----------------------------- 79 | 80 | In this section, the proposed complete interface for ``Code`` and ``TExp`` is 81 | given. 82 | 83 | A newtype is defined called ``Code``:: 84 | 85 | newtype Code m a = Code (m (TExp a)) 86 | 87 | There are three main constructs that the proposal affects. 88 | 89 | Quoting an expression ``e :: T`` now produces an expression of typed ``Quote m => Code m T``:: 90 | 91 | -- foo :: Quote m => m (TExp Int) 92 | foo :: Quote m => Code m Int 93 | foo = [|| 5 ||] 94 | 95 | Top-level splicing requires an expression of type ``Code Q T`` and produces a value of type ``T``:: 96 | 97 | bar :: Int 98 | bar = $$foo 99 | 100 | Nested splicing requires an expression of type ``Code m T`` and the overall 101 | type of the quotation is a union of the constraints on all the nested splices:: 102 | 103 | baz :: Quote m => Code m Int 104 | baz = [|| 1 + $$(foo) ||] 105 | 106 | The return type of the ``liftTyped`` method of the class ``Lift`` 107 | is changed from ``m (TExp a)`` to ``Code m a``.:: 108 | 109 | class Lift a where 110 | lift :: Quote m => a -> m Exp 111 | liftTyped :: Quote m => a -> Code m a 112 | 113 | The functions ``unsafeCodeCoerce`` and ``unTypeCode`` are introduced to work directly 114 | with ``Code``:: 115 | 116 | unsafeCodeCoerce :: m Exp -> Code m a 117 | unTypeCode :: Code m a -> m Exp 118 | 119 | There are still the normal functions for interacting with ``TExp a``:: 120 | 121 | unsafeTExpCoerce :: Quote m => m Exp -> m (TExp a) 122 | unsafeTExpCoerce = fmap unsafeExpToTExp 123 | TExp :: Exp -> TExp a 124 | unType :: TExp a -> Exp 125 | unType (TExp a) = a 126 | 127 | A new function is added to ``Language.Haskell.TH.Syntax`` in order to perform monadic actions inside of ``Code``:: 128 | 129 | liftCode :: m (TExp a) -> Code m a 130 | liftCode = Code 131 | 132 | And also a function which allows access to the wrapped ``TExp`` value:: 133 | 134 | examineCode :: Code m a -> m (TExp a) 135 | examineCode (Code m) = m 136 | 137 | ``Code`` is still exported though so users can pattern match on it themselves 138 | rather than using these convenience functions. 139 | 140 | It is also useful to implement a method to modifying the underlying monadic 141 | representation. For example, in order to handle additional effects before running 142 | a top-level splice:: 143 | 144 | hoistCode :: (forall a . m a -> n a) -> Code m a -> Code n a 145 | hoistCode f (Code a) = Code (f a) 146 | 147 | -- As an example, hoistCode can be used to handle a state effect 148 | handleState :: Code (StateT Int Q) a -> Code Q a 149 | handleState = hoistCode (flip runState 0) 150 | 151 | Two more useful combinators are ``bindCode`` and ``bindCode_`` which 152 | are versions of ``>>=`` and ``>>`` and interact nicely with QualifiedDo:: 153 | 154 | bindCode :: m a -> (a -> Code m b) -> Code m b 155 | bindCode q k = liftCode (q >>= examineCode . k) 156 | 157 | bindCode_ :: m a -> Code m b -> Code m b 158 | bindCode_ q c = liftCode (q >> examineCode c) 159 | 160 | The ``Code`` data constructor is also exposed to users in case they want to 161 | explicitly interact with the underlying monadic computation in another manner. 162 | 163 | 164 | Effect and Interactions 165 | ----------------------- 166 | The proposal solves the main problem because now it is easily possible to write 167 | instances for the ``Code`` type because it is no longer a composition of two 168 | type constructors. 169 | 170 | 171 | Costs and Drawbacks 172 | ------------------- 173 | 174 | The main drawback is that this will break all users of Typed Template Haskell who 175 | write type signatures. 176 | However, I feel like I am the only user so the impact will be minimal. 177 | 178 | 179 | Alternatives 180 | ------------ 181 | 182 | Unresolved Questions 183 | -------------------- 184 | 185 | 186 | Implementation Plan 187 | ------------------- 188 | Implementation is straightforward. 189 | -------------------------------------------------------------------------------- /proposals/0209-levity-polymorphic-lift.rst: -------------------------------------------------------------------------------- 1 | Levity-polymorphic `Lift` 2 | ========================= 3 | 4 | .. author:: Alec Theriault 5 | .. date-accepted:: 2019-04-17 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/merge_requests/789 7 | .. implemented:: 8.10 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | The ``Lift`` typeclass lets us lift values into typed or untyped Template Haskell expressions. 13 | 14 | :: 15 | 16 | class Lift t where 17 | lift :: t -> Q Exp 18 | liftTyped :: t -> Q (TExp t) 19 | 20 | newtype TExp a = TExp { unType :: Exp } 21 | 22 | One shortcoming of this class is that it does not let us lift values whose kind is not ``Type``. 23 | We propose to lift this restriction by making ``Lift`` and ``TExp`` levity polymorphic. 24 | 25 | :: 26 | 27 | class Lift (t :: TYPE r) where 28 | lift :: t -> Q Exp 29 | liftTyped :: t -> Q (TExp t) 30 | 31 | newtype TExp (t :: TYPE r) = TExp { unType :: Exp } 32 | 33 | Motivation 34 | ------------ 35 | The ``Lift`` class cannot currently handle unlifted types. This is a somewhat frustrating limitation 36 | since Template Haskell supports representing unlifted values, only they must be constructed 37 | manually. 38 | 39 | :: 40 | 41 | x :: Q Exp 42 | x = LitE (IntPrimL 1) -- yet we'd like to be able to write `lift 1#` 43 | 44 | The fact that ``TExp`` doesn't support unlifted types means that it is less expressive that ``Exp``. 45 | ``TExp`` is generally regarded as a more type-safe approach to Template Haskell, so users find 46 | themselves needing to choose between generating more performant code that uses unlifted types and 47 | using the more typesafe ``TExp``. The problems around ``TExp`` don't end there: if you omit a type 48 | signature, one can trick GHC 8.6.3 (and latest HEAD) into accepting invalid ``TExp``! 49 | 50 | :: 51 | 52 | {-# LANGUAGE MagicHash, TemplateHaskell #-} 53 | 54 | import GHC.Exts 55 | import Language.Haskell.TH.Syntax 56 | 57 | main = print =<< runQ (unTypeQ [|| I# $$e ||]) 58 | where e = [|| 1# ||] -- :: Q (TExp Int#) 59 | -- yet but adding this ^ signature causes a compile error! 60 | 61 | The current ``-XDeriveLift`` implementation has some special logic for handling data types with unlifted 62 | fields. Generalizing ``Lift`` would remove the need for any special cases. 63 | 64 | Proposed Change Specification 65 | ----------------------------- 66 | Change ``TExp``, ``Lift``, ``unTypeQ``, and ``unsafeTExpCoerce`` to take advantage of levity polymorphism: 67 | 68 | :: 69 | 70 | newtype TExp (t :: TYPE r) = TExp { unType :: Exp } 71 | 72 | unTypeQ :: forall (a :: TYPE r). Q (TExp a) -> Q Exp 73 | unTypeQ m = do { TExp e <- m 74 | ; return e } 75 | 76 | unsafeTExpCoerce :: forall (a :: TYPE r). Q Exp -> Q (TExp a) 77 | unsafeTExpCoerce m = do { e <- m 78 | ; return (TExp e) } 79 | 80 | class Lift (t :: TYPE r) where 81 | lift :: t -> Q Exp 82 | default lift :: (r ~ 'LiftedRep) => t -> Q Exp 83 | lift = unTypeQ . liftTyped 84 | 85 | liftTyped :: t -> Q (TExp t) 86 | 87 | Two important observations: 88 | 89 | 1. The ``r ~ 'LiftedRep`` is needed because GHC doesn't know how to handle levity polymorphic 90 | binders. It does mean that instances of ``Lift`` over unlifted types will need to manually 91 | implement both ``lift`` and ``liftTyped``. 92 | 93 | 2. By not providing a default implementation of ``liftTyped``, any existing empty instances of 94 | ``Lift`` will crash as opposed to loop. This does have the unpleasant side effect that there 95 | will be no way to write a CPP-free and backwards-compatible manual instance of ``Lift``. 96 | However, since the vast majority of instances can (and should!) be derived with 97 | ``-XDeriveLift``, which *is* backwards compatible, this is not a significant problem. 98 | 99 | Add to ``Language.Haskell.TH.Syntax`` a handful of new instances of ``Lift`` which are now valid: 100 | 101 | :: 102 | 103 | instance Lift Int# where ... 104 | instance Lift Word# where ... 105 | instance Lift Float# where ... 106 | instance Lift Double# where ... 107 | instance Lift Char# where ... 108 | instance Lift Addr# where ... 109 | 110 | Modify ``-XDeriveLift`` to generate typed and untyped quotes (for ``liftTyped`` and ``lift`` respectively). 111 | 112 | Effect and Interactions 113 | ----------------------- 114 | The proposed change would make it possible to lift values of unlifted kinds and would make it 115 | (officially) possibly for ``TExp`` to represent expressions of unlifted kinds. 116 | 117 | This proposal would also provide a means for trying out levity polymorphism in typeclasses (see 118 | sections 7.3 and 8.1 of the `Levity Polymorphism paper `_). 119 | Although there are `many classes which could benefit from this treatment `_, 120 | ``Lift`` is a good first candidate because it isn't too widely used and ``template-haskell`` 121 | isn't expected to be as stable and free of breakage as ``base``. There is already `a proposal `_ which aims to make typeclasses in ``base`` levity-polymorphic. 122 | 123 | Costs and Drawbacks 124 | ------------------- 125 | The main drawback is that uses of ``lift``, ``TExp``, ``unType``, ``unTypeQ``, and ``unsafeTExpCoerce`` which 126 | have visible type applications will be broken (since the type argument would now refer to the 127 | runtime rep). Here is an example: 128 | 129 | :: 130 | 131 | ghci> let rationalOne = lift @Rational 1 -- no longer works 132 | 133 | : error: 134 | • Expected kind ‘GHC.Types.RuntimeRep’, but ‘Rational’ has kind ‘*’ 135 | • In the type ‘Rational’ 136 | In the expression: lift @Rational 1 137 | In an equation for ‘it’: it = lift @Rational 1 138 | 139 | Any such uses should be easily fixable in a backwards compatible fashion by using explicit type 140 | signatures instead of type applications (or, if one wishes to continue using type applications, by 141 | adding an extra ``@_`` type argument first). 142 | 143 | In terms of development and maintainability, the cost is small: the prototype patch that implements 144 | this functionality ends up removing more lines from the compiler than it adds. 145 | 146 | The only other drawback is that beginners browsing the documentation for Template Haskell are more 147 | likely to be confused by the complex signature for the default implementations of the ``lift`` 148 | method. 149 | 150 | Alternatives 151 | ------------ 152 | None known. 153 | 154 | Unresolved Questions 155 | -------------------- 156 | If the proposal `Explicit specificity in type variable binders `_ 157 | were already implemented, we might be able to avoid breaking code which uses visible type 158 | application (on any of the functions whose signatures we are proposing to generalize). The idea 159 | would be to specify the ``RuntimeRep`` type variables as inferred. This would come at the cost of 160 | even more complicated type signatures though. 161 | 162 | Implementation Plan 163 | ------------------- 164 | I (Alec Theriault) will implement this change. The work is already 165 | done in `Phab:D5220 `_. 166 | -------------------------------------------------------------------------------- /proposals/0210-minimal-should-warn-extras.rst: -------------------------------------------------------------------------------- 1 | MINIMAL should warn about extra definitions 2 | =========================================== 3 | 4 | .. author:: Levent Erkok 5 | .. date-accepted:: 2019-03-14 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/16314 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | Currently, GHC issues no warnings if a class has a ``MINIMAL`` pragma requiring ``foo``, and yet you also 13 | give a default definition for ``foo``. This proposal suggests the addition of this warning. 14 | 15 | 16 | Motivation 17 | ------------ 18 | I was recently quite confused about an error message from GHC, originating from code like this:: 19 | 20 | class X a where 21 | foo :: a 22 | 23 | {-# MINIMAL foo #-} 24 | foo = undefined 25 | 26 | instance X Int 27 | 28 | For this, GHC says:: 29 | 30 | GHCi, version 8.6.3: http://www.haskell.org/ghc/ :? for help 31 | [1 of 1] Compiling Main ( a.hs, interpreted ) 32 | 33 | a.hs:7:10: warning: [-Wmissing-methods] 34 | • No explicit implementation for 35 | ‘foo’ 36 | • In the instance declaration for ‘X Int’ 37 | | 38 | 7 | instance X Int 39 | | 40 | 41 | This is arguably correct, but not helpful. Since I made ``foo`` part of ``MINIMAL``, GHC rightly complains the instance 42 | definition should not skip it. But that's very confusing: because I know I just added a default definition for it. Of 43 | course, the mistake I made was that I forgot to remove it from the ``MINIMAL`` pragma; but I was not warned about that. 44 | 45 | The important point is that the warning comes at the instantiation site instead of 46 | the class definition, which can be miles apart. Even worse: The class might be coming from a library and the library 47 | author was never warned about this obvious mistake. 48 | 49 | This proposal suggests that GHC should warn about this discrepancy right at the point where the ``class X`` 50 | is defined, with a message of the form:: 51 | 52 | You made `foo` MINIMAL, but also gave an explicit definition for it. 53 | 54 | Per usual GHC strategy, this can be tied to a flag named ``-Wredundant-minimal-methods`` or similar. This flag should be 55 | on by default. (Exact wording of the warning text and the flag name can be determined by the implementor.) 56 | 57 | I have filed this as a feature request: https://gitlab.haskell.org/ghc/ghc/issues/16314. Simon PJ asked me to 58 | create a proposal so it can gather feedback. 59 | 60 | Proposed Change Specification 61 | ----------------------------- 62 | 63 | The change is quite mimimal. First, we need a minor change to the user manual, where the grammar 64 | of ``MINIMAL`` descriptions are given as:: 65 | 66 | mindef ::= name 67 | | '(' mindef ')' 68 | | mindef '|' mindef 69 | | mindef ',' mindef 70 | 71 | This is already not quite correct, because GHC actually allows empty minimal declarations, as 72 | in ``{-# MINIMAL #-}``, which isn't in the language generated by this grammar. We should change it to:: 73 | 74 | mindef :: 75 | | mindef1 76 | 77 | mindef1 ::= name 78 | | '(' mindef1 ')' 79 | | mindef1 '|' mindef1 80 | | mindef1 ',' mindef1 81 | 82 | 83 | Abusing the notation in the obvious way, define the following function from a ``MINIMAL`` 84 | expression to a set of names:: 85 | 86 | required = Set.empty 87 | required name = Set.singleton name 88 | required ('(' expr ')') = required expr 89 | required (left '|' right) = required left `Set.intersection` required right 90 | required (left ',' right) = required left `Set.union` required right 91 | 92 | For each class declaration with a ``MINIMAL`` pragma, compute:: 93 | 94 | D = set of all methods with default definitions 95 | R = the required set, as defined above 96 | E = D `Set.difference` R 97 | 98 | Note that ``D`` should not contain definitions that have ``default signatures``, i.e., those 99 | with a default-definition only at a more specific type with extra constraints. See below in 100 | the "Effects and Interactions" section for the motivation on this. 101 | 102 | If ``E`` is not empty, then GHC should emit a warning saying the methods in ``E`` are required by 103 | the ``MINIMAL`` pragma but also are given a default definition. If ``E`` is empty, no warning is generated. 104 | 105 | As per usual GHC strategy, this warning should be tied to a flag, ``-Wredundant-minimal-methods``, 106 | though the implementor can choose something more appropriate. The flag should be on by default. 107 | 108 | Simon PJ comments: The ``MINIMAL`` definition requires that every method ``m`` in ``R`` 109 | is defined in the instance declaration. Giving a default method for ``m``, in the class declaration, is 110 | therefore redundant. The warning encourages the programmer either to remove the default definition 111 | or to adjust the ``MINIMAL`` pragma. 112 | 113 | Effect and Interactions 114 | ----------------------- 115 | 116 | If a method as a definition via the ``default signatures`` extension, then that definition should 117 | not be added to the set ``D`` as defined above. The motivation for this is that the author of 118 | the library provided a weaker definition (in the sense of the type) than required by the class for 119 | that particular method, and thus the author should be free to mention that method 120 | in the ``MINIMAL`` pragma without getting a warning. 121 | 122 | The presence of a definition with a default signature should be something that's checked at the 123 | instantiation site of this class, not at the definition site, for violations of the ``MINIMAL`` requirements. 124 | 125 | Costs and Drawbacks 126 | ------------------- 127 | Cost: The compiler probably already has all the necessary bits and pieces to do this in short order. 128 | For someone familiar with that part of the code, I doubt it's more than an afternoon worth of work; 129 | including test cases and integration. 130 | 131 | Drawbacks: I don't think there is any! 132 | 133 | Alternatives 134 | ------------ 135 | Do nothing. But in a large refactoring case (which prompted this proposal in the first place) it is 136 | much nicer to get warnings close to where the problem is, as opposed to later on. In the particular 137 | case of the class being defined in a library and the instance being in user code, this issue gets 138 | amplified as there is really nothing the user of the library can do. 139 | 140 | Unresolved Questions 141 | -------------------- 142 | None. 143 | 144 | Implementation Plan 145 | ------------------- 146 | TBD. 147 | -------------------------------------------------------------------------------- /proposals/0240-threaded-by-default.rst: -------------------------------------------------------------------------------- 1 | Compile with threaded RTS by default 2 | ==================================== 3 | 4 | .. author:: Artem Pelenitsyn 5 | .. date-accepted:: 2019-07-29 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/issues/16126 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | Today, in order to use the threaded variant of the runtime, one have to pass the ``-threaded`` flag. The proposal suggests making ``-threaded`` the default: in order to get the threaded RTS one would not have to do anything, while to fallback to the current, single-threaded mode, one would use the new ``-single-threaded`` flag. 13 | 14 | 15 | Motivation 16 | ------------ 17 | 18 | Parallel hardware is here. The overwhelming majority of GHC users probably has access to multiple cores. Parts of GHC's ``base`` library, as well as FFI implementation, utilize those resources. In this setting, **defaulting** to the single-threaded RTS seems to be a legacy, which is not only over-pessimistic about the program environment, but also leads to subtle crushes and deadlocks when those GHC features are in use. Here is the list of some of the known problems arising from the absence of ``-threaeded``. 19 | 20 | * Blocking FFI calls do not yield to other threads. Common use cases: 21 | 22 | * ``System.Process.waitForProcess`` blocks other threads. 23 | 24 | This becomes especially hard to debug when used transitevly trough some library (e.g. for `conduit-extra `_). 25 | 26 | * Foreign export and foreign import wrapper cannot be called by other threads. 27 | 28 | * The IO Manager only exists with ``-threaded``, which means that: 29 | 30 | * ``Control.Concurrent.STM.registerDelay`` aborts compilation without ``-threaded``. 31 | * Other uses of the event manager, such as ``getSystemEventManager`` fail. 32 | * ``System.Timeout`` falls back to an inefficient implementation. 33 | * Parallelism (``+RTS -N`) doesn't work. 34 | 35 | Here is a couple of more points, which cannot be classified as problems per se but still suggest going for the switch: 36 | 37 | * GHCi is built with ``-threaded`` by default, so using the same for binaries by default seems more consistent. 38 | 39 | * The new I/O manager for Windows (`!1224 `_) explicitly states that it is meant to be used with the threaded RTS. 40 | 41 | The proposal suggests avoiding these subtle problems by defaulting on the threaded RTS, and provide a way to fallback for users in need of single-threaded RTS mode for certain reasons (determinism, debugging, limited hardware, etc.). The latter can be done by the means of the new ``-single-threaded`` flag. 42 | 43 | 44 | Proposed Change Specification 45 | ----------------------------- 46 | 47 | The GHC compiler should start in ``-threaded`` mode by default. To fallback to the non-threaded mode, one would have to pass ``-single-threaded`` flag to the compiler. Otherwise, if a user pass the ``-threaded`` flag, they should get a warning that this flag has no effect anymore. 48 | 49 | 50 | Effect and Interactions 51 | ----------------------- 52 | 53 | The users of GHC will get their programs compiled with the threaded RTS by default. As unexpected as it may sound, the threaded RTS comes closer to the principle of the least surprise than the single-threaded RTS: many programs implicitly depending on tools such as ``forkIO`` can deadlock or crush with no good explanation with the single-threaded RTS. 54 | 55 | One of the main concerns with regards to the threaded RTS is parallel GC, which, anecdotally, almost certainly brings performance losses when not tuned carefully (cf., e.g. `#9221 `_). It is important to understand that parallel GC **is not implied** by ``-threaded``. The threaded mode still starts the program with one capability by default (unless ``-N`` is *explicitly* provided by the user), and GC runs sequential. 56 | 57 | Those who passed ``-threaded`` before will get a new warning, which might be painful (e.g. in the ``-Werror`` setting). 58 | 59 | 60 | Costs and Drawbacks 61 | ------------------- 62 | 63 | The main concern of this change is sudden changes to performance of compiled programs. In some cases it will improve, but in certain cases it may degrade, i.e. programs with no concurrent IO or programs running on single-threaded architectures might observe performance degradation upon updating to a newer GHC, and we should make sure to advertise the option to opt-out (via ``-single-threaded``) in the release notes. Changes in performance shouldn't be significant on a typical architecture given that parallel GC is not implied by ``-threaded``. 64 | 65 | Implementation has a very low cost and mostly concerns with figuring out necessary adaptations in the GHC test suite. 66 | 67 | 68 | Alternatives 69 | ------------ 70 | 71 | One alternative is status quo: default to the non-threaded RTS. This is a plausible option but feels outdated as of now. 72 | 73 | Another alternative suggested by Chris Done: 74 | 75 | GHC could determine at the Core/STG phase whether in the call graph from main, directly or transitively, there was a reference to ``fork#`` and other primops related to threading, and if neither ``-threaded`` nor ``-single-threaded`` was specified, it could warn "Your program may use multi-threaded code, please specify a mode by either: ``-threaded`` or ``-single-threaded``". 76 | 77 | This, in fact, is orthogonal to switching the deafult, as well as, requiring sugnificant implementation effort, allegedly. 78 | 79 | There is also a minor concern about the fallback flag name. Possible options that have been suggested so far are ``-single-threaded`` and ``-non-threaded``. 80 | 81 | 82 | Unresolved Questions 83 | -------------------- 84 | None. 85 | 86 | 87 | Implementation Plan 88 | ------------------- 89 | 90 | The implementation is started in `!538 `_. 91 | -------------------------------------------------------------------------------- /proposals/0277-winapi-callconv.rst: -------------------------------------------------------------------------------- 1 | Add winapi pseudo calling convention 2 | ==================================== 3 | 4 | .. author:: Tamar Christina 5 | .. date-accepted:: 2019-10-02 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/2485 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | On Windows when calling Windows API functions the calling conventions differ 14 | based on the architecture. The correct calling convention is often gotten wrong 15 | and GHC's suggestion is somewhat misleading. A new pseudo calling convention 16 | would solve these issues. 17 | 18 | Motivation 19 | ---------- 20 | 21 | On ``x86`` the default calling convention for Windows API calls is ``stdcall``, 22 | but on ``x86_64`` it is a variant of ``__fastcall``. 23 | 24 | Due to historical reasons people tend to think ``stdcall`` is the actual calling 25 | convention for both. On ``x86_64`` GHC would then generate the following warning 26 | 27 | :: 28 | 29 | * the 'stdcall' calling convention is unsupported on this platform, 30 | treating as ccall 31 | * When checking declaration: 32 | foreign import stdcall unsafe "static shlobj.h ShellExecuteA" c_ShellExecuteA 33 | 34 | 35 | Which is confusing as it's technically incorrect, but also users seem to replace the 36 | ``stdcall`` with ``cdecl`` in the source, which ends up breaking ``x86``. 37 | 38 | The solution to this ends up needing to use ``CPP`` to correctly choose the right 39 | calling convention. This ``CPP`` has to be repeated over and over and over again. 40 | 41 | Only looking at base we see this workaround is used: 42 | 43 | :: 44 | 45 | > git grep WINDOWS_CCONV | wc -l 46 | 87 47 | 48 | and in ``Win32`` 49 | 50 | :: 51 | 52 | > git grep WINDOWS_CCONV | wc -l 53 | 525 54 | 55 | Proposed Change 56 | --------------- 57 | 58 | The Haskell 2010 FFI specs allow for the flexibility to implement custom calling 59 | conventions. In fact we already do this with the ``CApi`` calling convention. 60 | 61 | It would simplify code, ease confusion and remove the need for ``CPP`` if we have 62 | a new pseudo calling convention ``winapi`` that is to be used specifically for calls 63 | to Windows API calls. 64 | 65 | Concretely I propose having the following: 66 | 67 | :: 68 | 69 | foreign import winapi "foo" c_foo :: IO () 70 | 71 | Where the compiler will determine the right calling convention to use for the 72 | target platform. 73 | 74 | I do not propose to change the warning, as for general code, ``cdecl`` is the right 75 | suggestion as native compilers will correctly reinterpret this to the x86_64 ABI 76 | calling convention. 77 | 78 | The maintenance should be fairly low as the ABI is set and won't change. 79 | 80 | I propose this to be added without needing a language extension, as it does not 81 | modify the language at all. It just makes use of clauses already in the existing 82 | specification. 83 | 84 | Drawbacks 85 | --------- 86 | 87 | Foreign exports become slightly confusing. The calling convention should really 88 | only be used for ``imports`` and ``wrappers`` but the FFI specification does not 89 | allow the flexibily of having calling conventions only one way. 90 | 91 | Alternatives 92 | ------------ 93 | 94 | The standard pattern used to work around this is usually 95 | 96 | :: 97 | 98 | #if defined(i386_HOST_ARCH) 99 | # define WINDOWS_CCONV stdcall 100 | #elif defined(x86_64_HOST_ARCH) 101 | # define WINDOWS_CCONV ccall 102 | #else 103 | # error Unknown mingw32 arch 104 | #endif 105 | 106 | An alternative implementation would be to extend the list of standard CPP defines 107 | for GHC to include ``WINDOWS_CCONV``. This however means you still need to have 108 | ``{-# LANGUAGE CPP #-}`` in order to use. 109 | 110 | Unresolved Questions 111 | -------------------- 112 | 113 | What should happen with ``foreign export`` code? 114 | 115 | I propose to let 116 | 117 | .. code-block:: 118 | 119 | foreign export winapi "foo" c_foo :: IO () 120 | 121 | 122 | have the same semantics as import for determining the calling convention. It 123 | has a valid use-case in if the user wants to create a "Windows API" style DLL. 124 | 125 | -------------------------------------------------------------------------------- /proposals/0313-countdown-benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tweag/ghc-proposals/cff853ec8c756d8c81abf69427036963edbafd4e/proposals/0313-countdown-benchmark.png -------------------------------------------------------------------------------- /proposals/0314-warn-noncanonical-monad-instance-by-default.rst: -------------------------------------------------------------------------------- 1 | Enable ``-Wnoncanonical-monad-instances`` and ``-Wnoncanonical-monoid-instances`` by default 2 | ============================================================================================ 3 | 4 | .. author:: Fumiaki Kinoshita 5 | .. date-accepted:: 2020-04-26 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3174 7 | .. implemented:: GHC-9.2 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | Currently, ``-Wnoncanonical-monad-instances`` and 14 | ``-Wnoncanonical-monoid-instances`` are not enabled in any of the 15 | default, ``-Wall`` and ``-Wcompat``. I propose enabling the warning by 16 | default. 17 | 18 | Motivation 19 | ---------- 20 | 21 | The prerequisite of the Phase 2 of `monad of no 22 | return `__ 23 | is to wait until “we’re confident that the majority of Hackage has 24 | reacted to the warning”. However, a warning that’s disabled unless you 25 | specify it individually gives infinitesimally small incentive to the 26 | ecosystem, so we can’t really expect them to react. In order to avoid 27 | catastrophic breakage like what we experienced when ``fail`` got 28 | removed, I think the warning should be enabled by default, not just in 29 | ``-Wall`` or ``-Wcompat``. 30 | 31 | I also propose enabling ``-Wnoncanonical-monoid-instances`` for the same 32 | reason. 33 | 34 | Proposed Change Specification 35 | ----------------------------- 36 | 37 | - Add ``-Wnoncanonical-monad-instances`` and 38 | ``-Wnoncanonical-monoid-instances`` to the set of default warnings. 39 | 40 | Examples 41 | -------- 42 | 43 | On GHC 8.8 (and 8.11.0.20200108), the following code compiles without 44 | warnings. 45 | 46 | .. code:: haskell 47 | 48 | data P a = P 49 | 50 | instance Functor P where 51 | fmap _ _ = P 52 | 53 | instance Applicative P where 54 | pure _ = P 55 | _ <*> _ = P 56 | 57 | instance Monad P where 58 | return _ = P 59 | _ >>= _ = P 60 | 61 | instance Semigroup (P a) where 62 | _ <> _ = P 63 | 64 | instance Monoid (P a) where 65 | mempty = P 66 | mappend _ _ = P 67 | 68 | With this proposal implemented, it would produce the following warning: 69 | 70 | :: 71 | 72 | /path/to/example.hs:12:3: warning: [-Wnoncanonical-monad-instances] 73 | Noncanonical ‘return’ definition detected 74 | ‘return’ will eventually be removed from the ‘Monad’ class in favour of ‘pure’. 75 | Either remove definition for ‘return’ (recommended) or define as ‘return = pure’ 76 | See also: https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/monad-of-no-return 77 | | 78 | 12 | return _ = P 79 | | ^^^^^^^^^^^^ 80 | 81 | /path/to/example.hs:12:3: warning: [-Wnoncanonical-monoid-instances] 82 | Noncanonical ‘mappend’ definition detected 83 | in the instance declaration for ‘Monoid (P a)’. 84 | ‘mappend’ will eventually be removed from the ‘Monoid’ class in favour of ‘(<>)’. 85 | Either remove definition for ‘mappend’ (recommended) or define as ‘mappend = (<>)’ 86 | See also: https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/semigroup-monoid 87 | | 88 | 20 | mappend _ _ = P 89 | 90 | Note that it also updates the warning messages, adding a URL and a 91 | notice that the method will be removed. 92 | 93 | Effect and Interactions 94 | ----------------------- 95 | 96 | Once this proposal is implemented, people are more likely to notice non 97 | canonical definitions of ``return`` and ``mappend``. 98 | 99 | Costs and Drawbacks 100 | ------------------- 101 | 102 | People are more likely get annoyed when they see the warnings. 103 | 104 | Alternatives 105 | ------------ 106 | 107 | Enable it only in one or more of ``-Wcompat`` or ``-Wall``. Not everyone 108 | specifies these flags so more packages are likely to break without a 109 | caution beforehand. 110 | 111 | Unresolved Questions 112 | -------------------- 113 | 114 | N/A 115 | 116 | Implementation Plan 117 | ------------------- 118 | 119 | Once approved, @fumieval can (hopefully) submit code changes. 120 | 121 | Endorsements 122 | ------------ 123 | -------------------------------------------------------------------------------- /proposals/0320-signature-instances.rst: -------------------------------------------------------------------------------- 1 | Defaults and backpack/hs-boot 2 | ============================= 3 | 4 | .. author:: John Ericson and Cale Gibbard on behalf of Obsidian Systems 5 | .. date-accepted:: 2020-05-14 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/-/issues/17190 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | Correct/clarify the meaning of instance declarations in hs-boot files 14 | and backpack signatures in the situations where an instance is to be 15 | required, but the corresponding class has a default type family 16 | instance. 17 | 18 | Motivation 19 | ---------- 20 | 21 | Presently, if one creates a class with an associated type that has a 22 | default, such as: 23 | 24 | .. code:: haskell 25 | 26 | -- in A.hs 27 | module A where 28 | class C a where 29 | type T a 30 | type T a = Int 31 | f :: a -> Int 32 | f _ = 0 33 | 34 | and then in an ``hs-boot`` file would like to demand an instance of that 35 | class for some type: 36 | 37 | .. code:: haskell 38 | 39 | -- in B.hs-boot 40 | module B where 41 | import A 42 | data X 43 | instance C X 44 | 45 | This results in a compiler panic, because GHC “can’t handle family 46 | instances in boot files”. Evidently, we’ve snuck a type family instance 47 | into what was meant to be an interface. 48 | 49 | This problem also occurs for backpack signatures, which are rather 50 | similar in many ways to hs-boot files. 51 | 52 | In both cases, trying to explicitly specify anything about the type 53 | family instance in an hs-boot file or backpack signature is currently an 54 | error (a more explicit one rather than a compiler panic). 55 | 56 | At the term level, the default is ignored, because ``hsig``/``hs-boot`` 57 | are not allowed to contain methods period: 58 | 59 | .. code:: haskell 60 | 61 | -- in B.hs-boot 62 | module B where 63 | import A 64 | data X 65 | instance C X 66 | -- T is unconstrained 67 | 68 | .. code:: haskell 69 | 70 | -- in B.hs-boot 71 | module B where 72 | import A 73 | data X 74 | instance C X 75 | f _ = 7 -- error 76 | 77 | This is blatantly inconsistent, with 3 ways to make it consistent: 78 | 79 | 1. Never allow (term or type level) items in instances, nor infer them 80 | from class defaults, in ``hsig``/``hs-boot`` files 81 | 82 | 2. Do allow items in instances, but apply defaults in 83 | ``hsig``/``hs-boot`` files 84 | 85 | 3. Do allow items in instances, but ignore defaults in 86 | ``hsig``/``hs-boot`` files 87 | 88 | Our approach is essentially to go with solution (1) here, with an 89 | understanding that (3) might eventually be desired if future proposals 90 | want to allow some type equality specifications in signatures. (2) seems 91 | needlessly confusing and restrictive. 92 | 93 | Proposed Change Specification 94 | ----------------------------- 95 | 96 | We propose that any instance in backpack signatures and hs-boot files, 97 | places no constraint on the terms and associated type family instances 98 | which may be specified by the corresponding class, regardless of whether 99 | there are defaults provided by the class specification. 100 | 101 | Examples 102 | -------- 103 | 104 | A.hs 105 | 106 | :: 107 | 108 | module A where 109 | 110 | class C a where 111 | type F a 112 | type F a = a -> a -- Default instance 113 | op :: a -> a 114 | 115 | foo :: C a => [a] -> F a 116 | foo = blah 117 | 118 | B.hs-boot 119 | 120 | :: 121 | 122 | module B where 123 | import A 124 | instance C Int 125 | 126 | C.hs 127 | 128 | :: 129 | 130 | module C where 131 | import {-# SOURCE #-} B 132 | 133 | wim :: [Int] -> F Int 134 | wim = foo -- OK 135 | 136 | wam :: [Int] -> Int -> Int 137 | wam = foo -- NOT OK 138 | 139 | B.hs 140 | 141 | :: 142 | 143 | module B where 144 | import A 145 | instance C Int where 146 | type F Int = [Int] 147 | op = reverse 148 | 149 | The instance ``C Int`` in B.hs-boot is legal, does not imply 150 | ``instance F Int = Int -> Int``, despite the default associated type 151 | declaration in the original definition of the class ``C``. Indeed, the 152 | final ``instance C Int`` in B.hs (shown above) might use an entirely 153 | different type instance than the default. 154 | 155 | This is all the same as class methods. The existence of a default method 156 | for ``op`` in the definition of ``C`` does not imply that the ``C Int`` 157 | instance (defined in B.hs presumably) uses that default method. 158 | 159 | Effect and Interactions 160 | ----------------------- 161 | 162 | The proposed change addresses the issue raised in the motivation section 163 | directly. I don’t immediately foresee any negative interactions with 164 | other language features. 165 | 166 | It’s not the intention of this proposal to specify anything with regards 167 | to whether type family instances, specifications of type equalities, or 168 | ordinary definitions (to be matched on some sort of equivalence 169 | perhaps), are permitted in hs-boot and backpack signatures. As of this 170 | writing, they’re not supported, but there are open GHC issues discussing 171 | adding support along these lines 172 | `#8441 `__ and 173 | `#12680 `__. 174 | 175 | Costs and Drawbacks 176 | ------------------- 177 | 178 | If you do want the default you have to repeat it. This is currently 179 | unsupported anyway at the type level, but we may wish to allow 180 | specifications of type family instances in ``hs-boot`` and ``hsig`` 181 | files in the future. 182 | 183 | Defaults in regular code allow what would have been a breaking change to 184 | be a non-breaking change. They won’t accomplish that for signatures and 185 | hs-boot files. However, the complicated variances surrounding backpack 186 | and classes (sigs and classes both being in negative position) makes 187 | this tricky to think about and of debatable value. 188 | 189 | There are better, more intentional ways to “upcast” libraries to an 190 | interface that the downstream library expects. We should explore 191 | extra-linguistic techniques for API evolution, rather than relying on 192 | cruder in-language-like defaulting for this, side-stepping this 193 | drawback. 194 | 195 | Alternatives 196 | ------------ 197 | 198 | There’s an option to eventually support specification of type family 199 | instances in backpack signatures and hs-boot files, where one would have 200 | the option of then regarding the default from the class as a 201 | specification which must be obeyed when an empty instance is given in 202 | the signature. That would mean that any non-default instance would be 203 | forced to be provided by the specification, and seems unhelpful at best. 204 | 205 | Unresolved Questions 206 | -------------------- 207 | 208 | On one hand, there are no term level equality constraints. On the other, 209 | we can simply require a module define any term-level method that the 210 | signature/boot file defines, or check for crude syntactic equality as a 211 | sound conservative approximation. 212 | 213 | Implementation Plan 214 | ------------------- 215 | 216 | John Ericson has already implemented this. `Pull Request 217 | #1776 `__. 218 | 219 | Endorsements 220 | ------------ 221 | 222 | Obsidian Systems has been working on this on behalf of MIRI. 223 | -------------------------------------------------------------------------------- /proposals/0344-negative-literals-improved.rst: -------------------------------------------------------------------------------- 1 | Negative Literals Improved 2 | ========================== 3 | 4 | .. author:: Vladislav Zavialov 5 | .. date-accepted:: 2020-07-22 6 | .. ticket-url:: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/3624 7 | .. implemented:: 9.0 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | 13 | At the moment, ``NegativeLiterals`` has the following issue, documented 14 | in the User’s Guide: 15 | 16 | One pitfall is that with ``NegativeLiterals``, ``x-1`` will be parsed 17 | as ``x`` applied to the argument ``-1``, which is usually not what 18 | you want. ``x - 1`` or even ``x- 1`` can be used instead for 19 | subtraction. 20 | 21 | We propose to fix this. 22 | 23 | Additionally, unboxed literals (e.g. ``-1#``) have the same issue even 24 | without the ``NegativeLiterals`` extension. We propose to fix this, too. 25 | 26 | Motivation 27 | ---------- 28 | 29 | 1. Having ``x-1`` parsed as ``x (-1)`` may violate users’ expectations. 30 | As evidence, see 31 | `#18022 `__. 32 | 33 | 2. Fixing this infelicity would make ``NegativeLiterals`` a subset of 34 | ``LexicalNegation``. 35 | 36 | Proposed Change Specification 37 | ----------------------------- 38 | 39 | When lexing a negative literal, require that it is *not preceded by a 40 | closing token*. See 41 | `#229 `__ 42 | for the definition of a closing token. 43 | 44 | Effect and Interactions 45 | ----------------------- 46 | 47 | - Code that relies on ``x-1`` being parsed as ``x (-1)`` will break. 48 | 49 | - Enabling ``-XLexicalNegation -XNegativeLiterals`` has the same effect 50 | as enabling ``-XLexicalNegation`` alone; however, enabling 51 | ``-XNegativeLiterals`` alone does not have the same effect, as it 52 | does not affect expressions such as ``-x``. In other words, 53 | ``NegativeLiterals`` becomes a subset of ``LexicalNegation``. 54 | 55 | Costs and Drawbacks 56 | ------------------- 57 | 58 | Changing the behavior of an existing extension may not be the best 59 | practice. 60 | 61 | Alternatives 62 | ------------ 63 | 64 | - Don’t change anything. 65 | - Deprecate ``NegativeLiterals`` in favor of ``LexicalNegation``. 66 | 67 | Unresolved Questions 68 | -------------------- 69 | 70 | None at the moment. 71 | 72 | Implementation Plan 73 | ------------------- 74 | 75 | Implemented in `Merge Request 76 | 3624 `__. 77 | -------------------------------------------------------------------------------- /proposals/0364-unify-natural.rst: -------------------------------------------------------------------------------- 1 | Unify ``Nat`` and ``Natural`` 2 | ============================= 3 | 4 | .. author:: Richard Eisenberg, inspired by Rinat Striungis 5 | .. date-accepted:: 2020-10-12 6 | .. ticket-url:: 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | GHC currently uses ``GHC.TypeLits.Nat`` to describe compile-time natural numbers 13 | but ``Numeric.Natural.Natural`` to describe runtime ones. This proposal unifies 14 | the two by making ``GHC.TypeLits.Nat`` a synonym for ``Numeric.Natural.Natural``. 15 | 16 | Motivation 17 | ---------- 18 | 19 | GHC should not have two different types to represent natural numbers. One is 20 | enough. The existence of the separate kind ``Nat`` and the impossibility of 21 | using ``Natural`` at compile time (and data constructors with ``Natural`` fields) is 22 | an unnecessary complication. It forces us to create 23 | redundant types with ``Nat`` fields in their constructors (making these types 24 | uninhabited at runtime) only for use at compile time. This is more cumbersome 25 | than the promotion of ordinary data types. 26 | 27 | Consider this data type with fields of type ``Natural``:: 28 | 29 | data Point = MkPoint Natural Natural 30 | 31 | ``Point`` is inhabited by terms, but not by types:: 32 | 33 | p = MkPoint 3 5 -- ok 34 | type P = MkPoint 3 5 -- not ok 35 | 36 | Alternatively, we could declare it with fields of type ``Nat``:: 37 | 38 | data Point = MkPoint Nat Nat 39 | 40 | Then it would have the opposite issue:: 41 | 42 | p = MkPoint 3 5 -- not ok 43 | type P = MkPoint 3 5 -- ok 44 | 45 | To avoid declaring two incompatible data types, we could add a parameter to ``Point``:: 46 | 47 | data Point n = MkPoint n n 48 | type PointT = Point Natural -- inhabited by terms 49 | type PointK = Point Nat -- inhabited by types 50 | 51 | However, this is a roundabout way to go about it, and in more involved 52 | scenarios requires additional machinery to support it (such as the ``Demote`` 53 | type family in the ``singletons`` package). By unifying ``Nat`` and 54 | ``Natural``, we avoid this issue entirely. 55 | 56 | Proposed Change Specification 57 | ----------------------------- 58 | * Add ``type Nat = Natural`` in ``GHC.TypeNats``. 59 | 60 | * Re-export ``Natural`` from ``GHC.TypeNats`` and 61 | ``GHC.TypeLits`` (along with the current re-export 62 | of ``Nat``). 63 | 64 | * Assign numbers in types to have kind ``Natural`` instead of kind ``Nat``. 65 | 66 | Effect and Interactions 67 | ----------------------- 68 | * Instances written about ``Nat`` may now need ``TypeSynonymInstances``, which 69 | is implied by ``FlexibleInstances``. Or, they could be written to use ``Natural`` 70 | instead of ``Nat``. 71 | 72 | * It is possible for someone to have separate instances today for ``Nat`` and 73 | ``Natural``, though it is unclear how an instance on ``Nat`` would be useful. 74 | Having two separate instances for these types will not be possible after this 75 | proposal is implemented. 76 | 77 | Otherwise, this change should be backward compatible. In particular, this proposal 78 | does *not* change parsing or other aspects of numbers written in types. For example, 79 | even though ``(-5 :: Natural)`` parses today (and throws a runtime error), that 80 | expression will *not* parse in types. 81 | 82 | 83 | Costs and Drawbacks 84 | ------------------- 85 | * We might be painting ourselves into a corner, having not yet worked out the 86 | way we will support other types of compile-time literals. But I (Richard) 87 | think this will be OK. 88 | 89 | 90 | Alternatives 91 | ------------ 92 | * Do nothing. 93 | 94 | 95 | Unresolved Questions 96 | -------------------- 97 | * None at this time. 98 | 99 | Implementation Plan 100 | ------------------- 101 | * This is already `implemented `_, 102 | by Rinat Striungis. 103 | 104 | -------------------------------------------------------------------------------- /proposals/0371-non-magical-eq.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Vladislav Zavialov 3 | date-accepted: "2021-05-10" 4 | ticket-url: "" 5 | implemented: "" 6 | --- 7 | 8 | This proposal was [discussed at this pull request](https://github.com/ghc-proposals/ghc-proposals/pull/371) and [amended by this one](https://github.com/ghc-proposals/ghc-proposals/pull/460). 9 | 10 | # Export `~` from `Data.Type.Equality` 11 | 12 | 13 | ## Motivation 14 | 15 | The `~` type operator is magical, in that it's always in scope and does not require `TypeOperators` to use. 16 | But `~~`, `:~:`, and `:~~:` are not magical in the same way, they are 17 | exported from `Data.Type.Equality` and require `TypeOperators`. 18 | 19 | This is a historical accident which we propose to correct. 20 | 21 | ## Proposed Change Specification 22 | 23 | * Do not bring `~` into scope magically, export it from `Data.Type.Equality`. 24 | 25 | * Re-export `~` from `Prelude`. 26 | 27 | * Drop the requieremnt to enable `TypeFamilies` or `GADTs` 28 | to use the `~` type operator. 29 | 30 | * Require `TypeOperators` to use the `~` type operator. 31 | 32 | ### Migration story 33 | 34 | Let `n` be the GHC version that implements this proposal. 35 | 36 | Starting with GHC `n`, include a compatibility fallback: 37 | 38 | 1. When the lookup for `~` fails because it is not in scope, 39 | assume it refers to `Data.Type.Equality.~`. 40 | When this happens and `-Wtype-equality-out-of-scope` (included in 41 | `-Wcompat`) is in effect, emit a warning. 42 | 43 | 2. When the use of `~` would have been rejected because `TypeOperators` are not 44 | enabled, accept the program regardless. 45 | When this happens and `-Wtype-equality-requires-operators` (enabled by 46 | default) is in effect, emit a warning. 47 | 48 | Starting with GHC `n+2`, enable both warnings by default. 49 | Either starting with GHC `n+8` or with the next major compiler version bump (GHC 50 | 10), whichever comes first, remove the compatibility fallback. 51 | 52 | ## Effect and Interactions 53 | 54 | * One less quirk. 55 | 56 | * The users are allowed to define their own ``~``. 57 | 58 | * The compiler internals are simplified, in particular things described in 59 | ``Note [eqTyCon (~) is built-in syntax]``. 60 | 61 | * Haddock documentation for ``~`` will get fixed (it is currently missing in 62 | the generated HTML). 63 | 64 | ## Costs and Drawbacks 65 | 66 | This is a breaking change: 67 | 68 | * Users will need to enable `TypeOperators` 69 | * Authors of custom preludes will likely want to re-export `(~)` 70 | 71 | ## Alternatives 72 | 73 | * Keep `~` special for historical reasons to avoid a breaking change. 74 | * A different migration schedule (e.g. include the warning in `-Wall` first). 75 | 76 | ## Unresolved Questions 77 | 78 | None. 79 | 80 | ## Implementation Plan 81 | 82 | There's a prototype implementation in [MR 4313](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/4313). 83 | -------------------------------------------------------------------------------- /proposals/0477-unicode-ellipsis.rst: -------------------------------------------------------------------------------- 1 | 2 | Unicode Ellipsis 3 | ================ 4 | 5 | .. author:: Ignat Insarov 6 | .. date-accepted:: 2022-03-30 7 | .. ticket-url:: 8 | .. implemented:: 9 | .. highlight:: haskell 10 | .. header:: This proposal was `discussed at this pull request `_. 11 | .. contents:: 12 | 13 | Motivation 14 | ---------- 15 | 16 | We already have beautiful Unicode make-up for all reserved symbols. And 17 | they look great! 18 | 19 | But no, not for all. The poor ellipsis ``..`` is left without. It wants 20 | to look like this: ``…``. 21 | 22 | Proposed Change Specification 23 | ----------------------------- 24 | 25 | When the ``UnicodeSyntax`` extension is enabled: 26 | 27 | 1. Make ``…`` accepted wherever ``..`` is accepted. 28 | 29 | 2. Allow ``…`` in situations like ``[False…]`` where ASCII syntax 30 | ``[False..]`` would be a parse error. *(This is automatically the 31 | case with the patch proposed below.)* *(Thanks to Jakob Brünker 32 | for*\ `pointing this 33 | out `__\ *.)* 34 | 35 | Examples 36 | -------- 37 | 38 | .. code:: haskell 39 | 40 | {-# language UnicodeSyntax #-} 41 | {-# language RecordWildCards #-} 42 | 43 | module X where 44 | 45 | import Prelude (Bool (…)) 46 | 47 | data Record = Record {value ∷ Bool} 48 | 49 | function ∷ Record → Bool 50 | function Record {…} = value 51 | 52 | booleans ∷ [Bool] 53 | booleans = [False…] 54 | 55 | Effect and Interactions 56 | ----------------------- 57 | 58 | Ellipsis gets its beautiful Unicode make-up. 59 | 60 | Costs and Drawbacks 61 | ------------------- 62 | 63 | There are no costs and no drawbacks. 64 | 65 | Alternatives 66 | ------------ 67 | 68 | There are no alternatives. 69 | 70 | Unresolved Questions 71 | -------------------- 72 | 73 | There are no unresolved questions. 74 | 75 | Implementation Plan 76 | ------------------- 77 | 78 | Apply this patch: 79 | 80 | .. code:: diff 81 | 82 | diff --git a/compiler/GHC/Parser/Lexer.x b/compiler/GHC/Parser/Lexer.x 83 | index d74d17be8f..4135372d31 100644 84 | --- a/compiler/GHC/Parser/Lexer.x 85 | +++ b/compiler/GHC/Parser/Lexer.x 86 | @@ -1063,6 +1063,7 @@ reservedSymsFM = listToUFM $ 87 | ,("-<<", ITLarrowtail NormalSyntax, NormalSyntax, xbit ArrowsBit) 88 | ,(">>-", ITRarrowtail NormalSyntax, NormalSyntax, xbit ArrowsBit) 89 | 90 | + , ("…", ITdotdot, UnicodeSyntax, 0 ) 91 | ,("∷", ITdcolon UnicodeSyntax, UnicodeSyntax, 0 ) 92 | ,("⇒", ITdarrow UnicodeSyntax, UnicodeSyntax, 0 ) 93 | ,("∀", ITforall UnicodeSyntax, UnicodeSyntax, 0 ) 94 | 95 | Endorsements 96 | ------------ 97 | 98 | There are no endorsements. 99 | -------------------------------------------------------------------------------- /proposals/0496-empty-record-wildcards.rst: -------------------------------------------------------------------------------- 1 | Allow record wildcards for empty records 2 | ============== 3 | 4 | .. author:: John Ericson (@Ericson2314) 5 | .. date-accepted:: 2022-07-03 6 | .. ticket-url:: 7 | .. implemented:: 8 | .. highlight:: haskell 9 | .. header:: This proposal was `discussed at this pull request `_. 10 | .. contents:: 11 | 12 | Allow record wild cards for empty records. 13 | This removes and artificial restriction, making the language simpler and more predictable. 14 | 15 | Motivation 16 | ---------- 17 | 18 | Currently this is allowed:: 19 | 20 | data Foo = Foo { a :: Int } 21 | 22 | f (Foo {..}) = 1 23 | 24 | x = Foo {..} 25 | where a = 1 26 | 27 | But this is not:: 28 | 29 | data Foo = Foo { } 30 | 31 | f (Foo {..}) = 1 32 | 33 | x = Foo {..} 34 | 35 | Prohibiting this doesn't seem good: 36 | 37 | #. It feels arbitrary and artificial. 38 | Does anyone expect this behavior? 39 | 40 | #. It is a pitfall for generated code, which cannot uniformly use record wildcard syntax no matter how many fields there are. 41 | 42 | Furthermore this is allowed :: 43 | 44 | data Foo = Foo { a :: Int } 45 | 46 | f (Foo { a = 1, ..}) = 1 47 | 48 | x = Foo { a = 1, ..} 49 | 50 | So we see ``..`` binding or using no fields isn't even consistently prohibited! 51 | 52 | Proposed Change Specification 53 | ----------------------------- 54 | 55 | Allow record wildcard syntax for empty variants. 56 | There are no (named) fields, so no variables are bound in patterns, and no variables are used in expressions. 57 | 58 | Examples 59 | -------- 60 | 61 | The second example in the motivation is allowed. 62 | 63 | This is also allowed:: 64 | 65 | data Foo = Foo -- no {} 66 | 67 | f (Foo {..}) = 1 68 | 69 | x = Foo {..} 70 | 71 | for it doesn't matter today whether empty variants are declared with ``{}``, and this should remain true. 72 | 73 | Effect and Interactions 74 | ----------------------- 75 | 76 | ``Foo {..}`` has the same meaning as ``Foo {}`` for an empty record. 77 | Note that means that:: 78 | 79 | data Foo = Foo 80 | f (Foo {..}) = 42 81 | 82 | is newly accepted just as:: 83 | 84 | data Foo = Foo 85 | f (Foo {}) = 42 86 | 87 | is today 88 | 89 | Costs and Drawbacks 90 | ------------------- 91 | 92 | Cannot think of any. 93 | 94 | 95 | Alternatives 96 | ------------ 97 | 98 | Do nothing. 99 | Can't think of anything else. 100 | 101 | Unresolved Questions 102 | -------------------- 103 | 104 | None at this time. 105 | 106 | Implementation Plan 107 | ------------------- 108 | 109 | This should be very easy. 110 | Perhaps we should use it as a mentoring exercise for new contributors. 111 | 112 | Endorsements 113 | ------------- 114 | 115 | There was positive feedback in https://github.com/ghc-proposals/ghc-proposals/issues/484 where this was previously brought up. 116 | -------------------------------------------------------------------------------- /rich-diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tweag/ghc-proposals/cff853ec8c756d8c81abf69427036963edbafd4e/rich-diff.png -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | np = import {}; 3 | in np.mkShell { buildInputs = [ np.pythonPackages.sphinx ]; } 4 | -------------------------------------------------------------------------------- /venv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$SHELL" ]; then 4 | SHELL=/bin/sh 5 | fi 6 | 7 | if [ ! -d _venv ]; then 8 | virtualenv _venv 9 | . _venv/bin/activate 10 | pip install sphinx 11 | exec $SHELL 12 | else 13 | . _venv/bin/activate 14 | exec $SHELL 15 | fi 16 | --------------------------------------------------------------------------------