Bikeshedding request for GHCi's :type

Hi devs, Over the weekend, I was pondering the Haskell course I will be teaching next year and shuddered at having to teach Foldable at the same time as `length`. So I implemented feature request #10963 (https://ghc.haskell.org/trac/ghc/ticket/10963), which allows for a way for a user to request a specialization of a type. It all works wonderfully, but there is a real user-facing design issue here around the default behavior of :type and whether or not to add new :type-y like commands. I have outlined the situation here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type I'd love some broad input on this issue. If you've got a stake in how this all works, please skim that wiki page and comment on #10963. Thanks! Richard

I think design A (deeply instantiate + generalize) produces the most sensible types. I don't know what the curly braces mean (perhaps that we can't use type application anymore since the order changed?) but I don't think they'd show up at all without -fprint-explicit-foralls, right? If so, I'm not too concerned about it. I also think 2C is a neat idea and should be explored further, but I don't think it should be the default behavior of :type. I've always expected :type to print the exact type we would infer for the expression. Perhaps instead of changing the default behavior of :type or adding new commands, we could add a flag to enhance :type's output. For example,
:type mapM mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b) :set -fprint-type-specializations :type mapM mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b) Possible Specializations: mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM :: (a -> Maybe b) -> [a] -> Maybe [b] ...
I think this could be useful even for experienced Haskellers, though I'm a bit concerned that printing the full type at the top will leave beginners as bewildered as ever.. Eric On Tue, Apr 26, 2016, at 06:08, Richard Eisenberg wrote:
Hi devs,
Over the weekend, I was pondering the Haskell course I will be teaching next year and shuddered at having to teach Foldable at the same time as `length`. So I implemented feature request #10963 (https://ghc.haskell.org/trac/ghc/ticket/10963), which allows for a way for a user to request a specialization of a type. It all works wonderfully, but there is a real user-facing design issue here around the default behavior of :type and whether or not to add new :type-y like commands. I have outlined the situation here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type
I'd love some broad input on this issue. If you've got a stake in how this all works, please skim that wiki page and comment on #10963.
Thanks! Richard _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Speaking as someone teaching his coworkers Haskell now, Eric's is the best
suggestion I've seen so far.
What I like about it:
* The original meaning of :type is unchanged.
* No new command is added (I prefer adding a flag to adding another
command).
* With the flag on, the full type is shown along with the possible
specializations (and good to note the list might not be exhaustive). This
way, beginners can still see what the type should look like even if they
want to ignore it for now. This is similar to learning to read Japanese by
using furigana. It may be a bit confusing for beginners at first, but I
expect they'll quickly learn to ignore it until they need it, and I agree
it will be useful for experienced Haskellers.
John
On Tue, Apr 26, 2016 at 5:18 PM, Eric Seidel
I think design A (deeply instantiate + generalize) produces the most sensible types. I don't know what the curly braces mean (perhaps that we can't use type application anymore since the order changed?) but I don't think they'd show up at all without -fprint-explicit-foralls, right? If so, I'm not too concerned about it.
I also think 2C is a neat idea and should be explored further, but I don't think it should be the default behavior of :type. I've always expected :type to print the exact type we would infer for the expression.
Perhaps instead of changing the default behavior of :type or adding new commands, we could add a flag to enhance :type's output. For example,
:type mapM mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b) :set -fprint-type-specializations :type mapM mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b) Possible Specializations: mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM :: (a -> Maybe b) -> [a] -> Maybe [b] ...
I think this could be useful even for experienced Haskellers, though I'm a bit concerned that printing the full type at the top will leave beginners as bewildered as ever..
Eric
On Tue, Apr 26, 2016, at 06:08, Richard Eisenberg wrote:
Hi devs,
Over the weekend, I was pondering the Haskell course I will be teaching next year and shuddered at having to teach Foldable at the same time as `length`. So I implemented feature request #10963 (https://ghc.haskell.org/trac/ghc/ticket/10963), which allows for a way for a user to request a specialization of a type. It all works wonderfully, but there is a real user-facing design issue here around the default behavior of :type and whether or not to add new :type-y like commands. I have outlined the situation here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type
I'd love some broad input on this issue. If you've got a stake in how this all works, please skim that wiki page and comment on #10963.
Thanks! Richard _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

On Wed, Apr 27, 2016 at 10:15 AM, John Leo
Speaking as someone teaching his coworkers Haskell now, Eric's is the best suggestion I've seen so far.
What I like about it: * The original meaning of :type is unchanged. * No new command is added (I prefer adding a flag to adding another command). * With the flag on, the full type is shown along with the possible specializations (and good to note the list might not be exhaustive). This way, beginners can still see what the type should look like even if they want to ignore it for now. This is similar to learning to read Japanese by using furigana. It may be a bit confusing for beginners at first, but I expect they'll quickly learn to ignore it until they need it, and I agree it will be useful for experienced Haskellers.
Perhaps a pleasant solution would be to borrow a convention from the PostgreSQL community's interactive console psql and its meta-commands: http://www.postgresql.org/docs/current/static/app-psql.html#APP-PSQL-META-CO... For example:
\d[S+] [ pattern ]
For each [object] matching the pattern, show all columns, their types, the tablespace (if not the default) and any special attributes such as NOT NULL or defaults. […] The command form \d+ is identical, except that more information is displayed: any comments associated with the columns of the table are shown, as is the presence of OIDs in the table, the view definition if the relation is a view, a non-default replica identitysetting.
Many psql commands use this convention: add a + to the end of the command, and you get extra information. It’s quite nmemonic.

Hello Richard,
I think that `:type` should report the real type of an expressions (i.e.,
the fully generalized inferred type, just like it does now). Certainly I
wouldn't want `:type` to show me some kind of (more or less) arbitrary
specialization of the type.
It could be useful to have a ghci command that would show all
instantiations of a class method (just 1 level deep) using the instances
that are currently in scope. This would be essentially a combination of
`:info` on a class and a method. For example, this is what it would look
like on some of the methods in 7.10's Prelude:
:inst length
length :: [a] -> Int
length :: Maybe a -> Int
length :: Either a b -> Int
length :: (a,b) -> Int
:inst (==)
(==) :: Integer -> Integer -> Bool
(==) :: Word -> Word -> Bool
...
(==) :: Eq a => [a] -> [a] -> Bool -- Note that we only instantiate the
outer class
...
(==) :: (Eq a, Eq b, Eq c) => (a,b,c) -> (a,b,c) -> Bool -- ditto
:inst mapM
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b)
mapM :: Monad m => (a -> m b) -> Either e a -> m (Either e b)
mapM :: Monad m => (a -> m b) -> (e,a) -> m (e,b)
This could be generalized to expressions, rather than just methods, but for
expressions with multiple constraints one could get an explosion of
possible instantiations. However, it would be quite cool to allow things
like this:
:inst 1
1 :: Word
1 :: Integer
1 :: Int
1 :: Float
1 :: Double
Anyway, just some ideas.
-Iavor
On Wed, Apr 27, 2016 at 8:16 AM, Manuel Gómez
On Wed, Apr 27, 2016 at 10:15 AM, John Leo
wrote: Speaking as someone teaching his coworkers Haskell now, Eric's is the best suggestion I've seen so far.
What I like about it: * The original meaning of :type is unchanged. * No new command is added (I prefer adding a flag to adding another command). * With the flag on, the full type is shown along with the possible specializations (and good to note the list might not be exhaustive). This way, beginners can still see what the type should look like even if they want to ignore it for now. This is similar to learning to read Japanese by using furigana. It may be a bit confusing for beginners at first, but I expect they'll quickly learn to ignore it until they need it, and I agree it will be useful for experienced Haskellers.
Perhaps a pleasant solution would be to borrow a convention from the PostgreSQL community's interactive console psql and its meta-commands:
http://www.postgresql.org/docs/current/static/app-psql.html#APP-PSQL-META-CO...
For example:
\d[S+] [ pattern ]
For each [object] matching the pattern, show all columns, their types, the tablespace (if not the default) and any special attributes such as NOT NULL or defaults. […] The command form \d+ is identical, except that more information is displayed: any comments associated with the columns of the table are shown, as is the presence of OIDs in the table, the view definition if the relation is a view, a non-default replica identitysetting.
Many psql commands use this convention: add a + to the end of the command, and you get extra information. It’s quite nmemonic. _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

I agree with Iavor that :type should report the real type. I see this only stymieing and frustrating efforts to teach the language. I do like the :inst idea.
On Apr 27, 2016, at 12:22 PM, Iavor Diatchki
wrote: Hello Richard,
I think that `:type` should report the real type of an expressions (i.e., the fully generalized inferred type, just like it does now). Certainly I wouldn't want `:type` to show me some kind of (more or less) arbitrary specialization of the type.
It could be useful to have a ghci command that would show all instantiations of a class method (just 1 level deep) using the instances that are currently in scope. This would be essentially a combination of `:info` on a class and a method. For example, this is what it would look like on some of the methods in 7.10's Prelude:
:inst length length :: [a] -> Int length :: Maybe a -> Int length :: Either a b -> Int length :: (a,b) -> Int
:inst (==) (==) :: Integer -> Integer -> Bool (==) :: Word -> Word -> Bool ... (==) :: Eq a => [a] -> [a] -> Bool -- Note that we only instantiate the outer class ... (==) :: (Eq a, Eq b, Eq c) => (a,b,c) -> (a,b,c) -> Bool -- ditto
:inst mapM mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b) mapM :: Monad m => (a -> m b) -> Either e a -> m (Either e b) mapM :: Monad m => (a -> m b) -> (e,a) -> m (e,b)
This could be generalized to expressions, rather than just methods, but for expressions with multiple constraints one could get an explosion of possible instantiations. However, it would be quite cool to allow things like this:
:inst 1 1 :: Word 1 :: Integer 1 :: Int 1 :: Float 1 :: Double
Anyway, just some ideas.
-Iavor
On Wed, Apr 27, 2016 at 8:16 AM, Manuel Gómez
mailto:targen@gmail.com> wrote: On Wed, Apr 27, 2016 at 10:15 AM, John Leo mailto:leo@halfaya.org> wrote: Speaking as someone teaching his coworkers Haskell now, Eric's is the best suggestion I've seen so far.
What I like about it: * The original meaning of :type is unchanged. * No new command is added (I prefer adding a flag to adding another command). * With the flag on, the full type is shown along with the possible specializations (and good to note the list might not be exhaustive). This way, beginners can still see what the type should look like even if they want to ignore it for now. This is similar to learning to read Japanese by using furigana. It may be a bit confusing for beginners at first, but I expect they'll quickly learn to ignore it until they need it, and I agree it will be useful for experienced Haskellers.
Perhaps a pleasant solution would be to borrow a convention from the PostgreSQL community's interactive console psql and its meta-commands: http://www.postgresql.org/docs/current/static/app-psql.html#APP-PSQL-META-CO... http://www.postgresql.org/docs/current/static/app-psql.html#APP-PSQL-META-CO...
For example:
\d[S+] [ pattern ]
For each [object] matching the pattern, show all columns, their types, the tablespace (if not the default) and any special attributes such as NOT NULL or defaults. […] The command form \d+ is identical, except that more information is displayed: any comments associated with the columns of the table are shown, as is the presence of OIDs in the table, the view definition if the relation is a view, a non-default replica identitysetting.
Many psql commands use this convention: add a + to the end of the command, and you get extra information. It’s quite nmemonic. _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org mailto:ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

I have collected feedback gleaned here, on the ticket, and on reddit and summarized here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type#Summaryoffeedbackabou...
That summary includes this concrete proposal:
1. Ask for concrete suggestions about names for the new commands.
2. Use these names on my current implementation (which prints out only one specialization)
3. Post a feature request looking for more specializations.
I simply don't have time to specify a design or implement an algorithm for printing out multiple specializations. Furthermore, my current implementation meets all specifications proffered for printing out multiple specializations, for all values of "multiple" that equal 1. It is easy to extend later.
Separately, there is a groundswell of support for :doc, but that's beyond the scope of my work on this point. (I personally would love :doc, too.)
So, what shall we name the two new commands?
1. A new command that specializes a type. (Currently with one specialization, but perhaps more examples in the future.)
2. A new command that preserves specialized type variables so that users of TypeApplications know what type parameters to pass in next.
I have suggested :type-def for (1) and :type-spec for (2). I don't strongly like either. :examples and :inst have been suggested for (1). Any other ideas?
Thanks!
Richard
On Apr 26, 2016, at 9:08 AM, Richard Eisenberg
Hi devs,
Over the weekend, I was pondering the Haskell course I will be teaching next year and shuddered at having to teach Foldable at the same time as `length`. So I implemented feature request #10963 (https://ghc.haskell.org/trac/ghc/ticket/10963), which allows for a way for a user to request a specialization of a type. It all works wonderfully, but there is a real user-facing design issue here around the default behavior of :type and whether or not to add new :type-y like commands. I have outlined the situation here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type
I'd love some broad input on this issue. If you've got a stake in how this all works, please skim that wiki page and comment on #10963.
Thanks! Richard _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Hi Richard,
I like your decision and plan.
Thank you a lot of work, for community.
About new command name for (1):
Most users, perhaps, have entered the `:t` rather than `:type`.
ghci> :t length
In the same way, how about a full name and abbreviation name for (1).
For example, we prepare `:type-default` and `:td`.
ghci> :td length
So they don't misunderstand that it is "typedef".
I also like `:type!` and `:types` with Jack :)
ghci> :t! length
Regards,
Takenobu
2016-05-03 5:10 GMT+09:00 Richard Eisenberg
I have collected feedback gleaned here, on the ticket, and on reddit and summarized here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type#Summaryoffeedbackabou...
That summary includes this concrete proposal: 1. Ask for concrete suggestions about names for the new commands. 2. Use these names on my current implementation (which prints out only one specialization) 3. Post a feature request looking for more specializations.
I simply don't have time to specify a design or implement an algorithm for printing out multiple specializations. Furthermore, my current implementation meets all specifications proffered for printing out multiple specializations, for all values of "multiple" that equal 1. It is easy to extend later.
Separately, there is a groundswell of support for :doc, but that's beyond the scope of my work on this point. (I personally would love :doc, too.)
So, what shall we name the two new commands?
1. A new command that specializes a type. (Currently with one specialization, but perhaps more examples in the future.)
2. A new command that preserves specialized type variables so that users of TypeApplications know what type parameters to pass in next.
I have suggested :type-def for (1) and :type-spec for (2). I don't strongly like either. :examples and :inst have been suggested for (1). Any other ideas?
Thanks! Richard
On Apr 26, 2016, at 9:08 AM, Richard Eisenberg
wrote: Hi devs,
Over the weekend, I was pondering the Haskell course I will be teaching next year and shuddered at having to teach Foldable at the same time as `length`. So I implemented feature request #10963 ( https://ghc.haskell.org/trac/ghc/ticket/10963), which allows for a way for a user to request a specialization of a type. It all works wonderfully, but there is a real user-facing design issue here around the default behavior of :type and whether or not to add new :type-y like commands. I have outlined the situation here: https://ghc.haskell.org/trac/ghc/wiki/Design/GHCi/Type
I'd love some broad input on this issue. If you've got a stake in how this all works, please skim that wiki page and comment on #10963.
Thanks! Richard _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
participants (7)
-
Christopher Allen
-
Eric Seidel
-
Iavor Diatchki
-
John Leo
-
Manuel Gómez
-
Richard Eisenberg
-
Takenobu Tani