[GHC] #14088: Allow users to omit`forall`
#14088: Allow users to omit`forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature | Status: new request | Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Just an idea I wanted to get out there, I don't think it causes parsing ambiguity {{{#!hs -- id :: forall a. a -> a id :: a. a -> a -- everywhere :: (forall b. Term b => b -> b) -> (forall a. Term a => a -> a) everywhere :: (b. Term b => b -> b) -> (a. Term a => a -> a) }}} I think it looks beautiful but clearly more difficult to Google or grep for. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14088: Allow users to omit `forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14088: Allow users to omit `forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by AntC): Hmm so {{{ f :: forall a b. a -> b -> a }}} becomes {{{ f :: a b. a -> b -> a }}} That initial `a b` looks like type application. {{{ g :: b.Foo -> Int }}} You probably meant {{{ g :: B.Foo -> Int }}} If you think `forall` is too verbose, you could use ∀ (?) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14088: Allow users to omit `forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): I don't support this idea. The issue is that in a type signature like `forall a b. a b`, there are two different varieties of type variables. There are type variable //binders// which appear between the `forall` and the dot (e.g., the `a` and `b` in `forall a b.`), and type variable //types//, which occur to right of the dot (e.g., the `a` and `b` in `. a b`). Syntactically, however, the difference between these two is not always so clear. This is where the `forall` keyword is extremely helpful to the reader. It gives a clear indication that what follows are type variable binders and not proper types. If we allow `forall` to be omitted, however, mentally parsing type signatures will become more of a chore. For instance, if you have this type signature: {{{#!hs f :: a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz. a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz }}} When I start reading the type of `f`, I have no idea if I'm looking at binders or types. I have to reserve extra lookahead to figure out what I'm looking at. With `forall`, this isn't an issue, because I can know instantly where the binders start. I'm not even sure what omitting `forall` even buys you. As AntC says, if you wish to write terser code, this is a perfectly cromulent thing to do: {{{ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE UnicodeSyntax #-} id :: ∀ a. a -> a id x = x }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14088: Allow users to omit `forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: wontfix | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Iceland_jack): * status: new => closed * resolution: => wontfix Comment: Yeah I didn't think this would gain traction and I agree that it complicates parsing, but it was too cute not to get the idea out. Thanks for the feedback! -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#14088: Allow users to omit `forall` -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: wontfix | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Krzysztof Gogolewski <krz.gogolewski@…>): In [changeset:"08b3db7e670d7a142244466f1722cb48ab82f1f5/ghc" 08b3db7e/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="08b3db7e670d7a142244466f1722cb48ab82f1f5" Use an accumulator version of tyCoVarsOfType Summary: This is part 1 from #14880: factor out a worker for the tyCoVarsOf... family of function, implementing them in terms of VarSet, but with accumulator-style (like in `FV`) built in, and with the same kind of pre-insert lookup; this has shown to perform better than either FV or plain VarSet in this particular scenario. Original notes from simonpj: In TyCoRep we now have tyCoVarsOfType implemented 1) Using FV -- this is the baseline version in GHC today 2) Using VarSets via unionVarSet 3) Using VarSets in accumulator-style In this patch (3) is enabled. When compiling perf/compiler/T5631 we get Compiler allocs (1) 1,144M (2) 1,175M (3) 1,142M The key new insight in (3) is this: ty_co_vars_of_type (TyVarTy v) is acc | v `elemVarSet` is = acc | v `elemVarSet` acc = acc <---- NB! | otherwise = ty_co_vars_of_type (tyVarKind v) is (extendVarSet acc v) Notice the second line! If the variable is already in the accumulator, don't re-add it. This makes big difference. Without it, allocation is 1,169M or so. One cause is that we only take the free vars of its kind once; that problem will go away when we do the main part of #14088 and close over kinds /afterwards/. But still, another cause is perhaps that every insert into a set overwrites the previous item, and so allocates a new path to the item; it's not a no-op even if the item is there already. Why use (3) rather than (1)? Becuase it just /has/ to be better; * FV carries around an InterestingVarFun, which does nothing useful here, but is tested at every variable * FV carries around a [Var] for the deterministic version. For this very hot operation (finding free vars) I think it makes sense to have speical purpose code. On the way I also simplified the (less used) coVarsOfType/Co family to use FV, by making serious use of the InterestingVarFun! Test Plan: validate, nofib Reviewers: simonpj, bgamari Reviewed By: simonpj Subscribers: rwbarton, carter GHC Trac Issues: #14880 Differential Revision: https://phabricator.haskell.org/D5141 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14088#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC