[GHC] #12541: RFC: Implicit parentheses in GHCi
GHC
ghc-devs at haskell.org
Fri Aug 26 01:27:19 UTC 2016
#12541: RFC: Implicit parentheses in GHCi
-------------------------------------+-------------------------------------
Reporter: Iceland_jack | Owner:
Type: feature | Status: new
request |
Priority: normal | Milestone:
Component: GHCi | Version: 8.0.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:
-------------------------------------+-------------------------------------
I've been making a few tickets lately that aren't technical but small
things that would streamline my interactive experience. Please close if
this is not the place for it. ''Caveat lector'': long and boring read
ahead.
= Code =
{{{#!hs
data Op = Add | Mul deriving Show
data Exp = Op Op | Lit Int | Exp :$ Exp deriving Show
infixl :$
}}}
= Motivation =
I often want to see the “progression” of applying an operator to arguments
one by one. There are several ways of doing this:
{{{#!hs
>>> :t (:$)
>>> :t (Op Add :$)
>>> :t Op Add :$ Lit 10
}}}
{{{#!hs
>>> :t (:$)
>>> :t (Op Add :$)
>>> :t (Op Add :$) (Lit 10)
}}}
{{{#!hs
>>> :t (:$)
>>> :t (:$) (Op Add)
>>> :t (:$) (Op Add) (Lit 10)
}}}
{{{#!hs
>>> :t (:$)
>>> :t (:$) (Op Add)
>>> :t Op Add :$ Lit 10
}}}
Look at all of those parentheses! Every step adds or removes (or requires
navigation around) parentheses.
= `tl;dr`: this is annoying to type =
I'm writing this out in full not just because I get a sick joy out of it
but to hammer the point home.
=== First example ===
We wrap `:$` in parentheses, navigate around them to make a section and
then remove them:
{{{#!hs
>>>
>>> :t (:$)␣
-- C-m
>>>
-- C-p
>>> :t (:$)␣
-- C-a
>>> ␣:t (:$)
-- C-f, C-f, C-f, C-f
>>> :t (␣:$)
>>> :t (Op Add ␣:$)
-- C-m
>>>
-- C-p
>>> :t (Op Add :$)␣
-- C-h
>>> :t (Op Add :$␣
>>> :t (Op Add :$ Lit 10
-- C-a
>>> ␣:t (Op Add :$ Lit 10
-- C-f, C-f, C-f
>>> :t ␣(Op Add :$ Lit 10
-- C-d
>>> :t ␣Op Add :$ Lit 10
}}}
=== Second example ===
We wrap `:$` in parentheses, navigate around them to make a section and
then wrap the argument in parentheses:
{{{#!hs
>>>
>>> :t (:$)␣
-- C-m
>>>
-- C-p
>>> :t (:$)␣
-- C-a
>>> ␣:t (:$)
-- C-f, C-f, C-f, C-f
>>> :t (␣:$)
>>> :t (Op Add ␣:$)
-- C-m
>>>
-- C-p
>>> :t (Op Add :$)␣
>>> :t (Op Add :$) (Lit 10)␣
}}}
=== Third example ===
Wrap everything in parentheses, on a good day I will remember that the
arguments need parentheses:
{{{#!hs
>>>
>>> :t (:$)␣
-- C-m
>>>
-- C-p
>>> :t (:$)␣
>>> :t (:$) (Op Add)␣
-- C-m
>>>
-- C-p
>>> :t (:$) (Op Add)␣
>>> :t (:$) (Op Add) (Lit 10)␣
}}}
((On every other day I will forget that `Op Add` is an application and
write..))
{{{#!hs
>>> :t (:$)␣
>>> :t (:$) Add␣
-- M-b
>>> :t (:$) ␣Add
>>> :t (:$) (Op ␣Add
-- C-e
>>> :t (:$) (Op Add␣
>>> :t (:$) (Op Add)␣
}}}
=== Fourth example ===
Wrap operator and argument, remove both pairs of parentheses:
{{{#!hs
>>>
>>> :t (:$)␣
-- C-m
>>>
-- C-p
>>> :t (:$)␣
>>> :t (:$) (Op Add)␣
-- C-m
>>>
-- C-p
>>> :t (:$) (Op Add)␣
-- C-a
>>> ␣:t (:$) (Op Add)
-- C-f, C-f, C-f
>>> :t ␣(:$) (Op Add)
-- C-d, C-d, ...
>>> :t ␣Op Add)
-- C-e
>>> :t Op Add)␣
-- C-h
>>> :t Op Add␣
>>> :t Op Add :$ Lit 10␣
}}}
= Proposal =
Long story short this involves a lot of manipulation of terms
(deleting/rewriting, cutting/pasting), jumping around and adding or
removing parentheses.
My proposal is to make GHCi a bit smarter in how it accepts operators and
sections, to a first approximation it would be as if there were implicit
`'(' ++ cmd ++ ')'` around the command. Let's see how I picture this would
work:
{{{#!hs
>>> :t :$
>>> :t Op Add :$
>>> :t Op Add :$ Lit 10
}}}
This may feel disconcerting since this is not valid syntax for operators
or sections, but I think it would be fine. For example both `:info :$` and
`:info (:$)` work. This would take me a lot less time to write! No
parentheses and minimal jumping around.
This would make it very simple to get the right section of an operator:
{{{#!hs
>>> :t >>=
>>> :t >>= id
}}}
and could be extended to work with infix functions as well, I would
probably use `flip` a whole lot less:
{{{#!hs
>>> :t `take`
-- ^ probably shouldn't work, but allows for less skipping
>>> :t `take` "wabalabadubdub"
>>> :t 10 `take` "wabalabadubdub"
}}}
The reason why I said “to a first approximation” is that `:$) (Op Add`
should obviously not be valid.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12541>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list