Allow ambiguous types (with warning) by default

The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?

I'm strongly against this, for a multitude of reasons. There's already a mechanism for doing what you want -- type defaulting. See also https://ghc.haskell.org/trac/ghc/ticket/8171 . On 12/5/2015 11:38 PM, David Feuer wrote:
The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

We could have a LANGUAGE pragma that makes the language easier for
beginners.
Provided it would not change anything major, otherwise it will be hard to
decide how much to simplify the language.
We can restrict it to only enabling some other extensions, one of which
could be AllowAmbiguousTypes.
On 6 December 2015 at 04:51, David Kraeutmann
I'm strongly against this, for a multitude of reasons. There's already a mechanism for doing what you want -- type defaulting. See also https://ghc.haskell.org/trac/ghc/ticket/8171 .
On 12/5/2015 11:38 PM, David Feuer wrote:
The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ 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
-- Regards Sumit Sahrawat

I don't think it'll make the language easier for beginners. It'd just be hidden type defaulting with much more severe consequences (since it's uncontrolled). Never mind that this will cause instance selection to be nondeterministic and very weird in general (the type of an expression will depend on what instances are in scope). On 12/6/2015 12:26 AM, Sumit Sahrawat, Maths & Computing, IIT (BHU) wrote:
We could have a LANGUAGE pragma that makes the language easier for beginners. Provided it would not change anything major, otherwise it will be hard to decide how much to simplify the language. We can restrict it to only enabling some other extensions, one of which could be AllowAmbiguousTypes.
On 6 December 2015 at 04:51, David Kraeutmann
wrote: I'm strongly against this, for a multitude of reasons. There's already a mechanism for doing what you want -- type defaulting. See also https://ghc.haskell.org/trac/ghc/ticket/8171 .
On 12/5/2015 11:38 PM, David Feuer wrote:
The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ 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

So you are saying you want users to write a ton of code that happens to
have signatures that can never be called and only catch it when they go to
try to actually use it in a concrete situation much later?
I don't really show how this would be a better default.
When and if users see the problem later they have to worry about if they
are doing something wrong at the definition site or the call site. With the
status quo it complains at the right time that you aren't going to sit
there flailing around trying to fix a call site that can never be fixed.
-Edward
On Sat, Dec 5, 2015 at 5:38 PM, David Feuer
The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

No, I want it to *warn* by default. If I write foo :: something that will fail the ambiguity check bar = something that uses foo in a (necessarily) ambiguous way the current default leads me to do this: 1. Attempt to compile. Get an ambiguity error on foo whose exact cause is hard for me to see. 2. Enable AllowAmbiguousTypes and recompile. Get an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 3. Fix foo, and disable AllowAmbiguousTypes. I'd much rather go with 1. Attempt to compile. Get an ambiguity *warning* on foo whose exact cause is hard for me to see, but also an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 2. Fix foo. Simple example of how it is currently:
let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:14:12: Couldn't match expected type ‘F a’ with actual type ‘F a0’ NB: ‘F’ is a type function, and may not be injective The type variable ‘a0’ is ambiguous In the ambiguity check for the type signature for ‘foo’: foo :: forall a. Num a => F a To defer the ambiguity check to use sites, enable AllowAmbiguousTypes In the type signature for ‘foo’: foo :: Num a => F a Couldn't match what with what? Huh? Where did a0 come from?
:set -XAllowAmbiguousTypes let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:16:61:
Couldn't match expected type ‘Int’ with actual type ‘F a0’
The type variable ‘a0’ is ambiguous
In the expression: foo
In an equation for ‘bar’: bar = foo
Aha! That's the problem! It doesn't know what a0 is! How can I tell it
what a0 is? Oh! I can't, because foo doesn't give me a handle on it.
Guess I have to fix foo.
I'd really, really like to get *both* of those messages in one go,
with the first one preferably explaining itself a bit better.
On Sat, Dec 5, 2015 at 11:51 PM, Edward Kmett
So you are saying you want users to write a ton of code that happens to have signatures that can never be called and only catch it when they go to try to actually use it in a concrete situation much later?
I don't really show how this would be a better default.
When and if users see the problem later they have to worry about if they are doing something wrong at the definition site or the call site. With the status quo it complains at the right time that you aren't going to sit there flailing around trying to fix a call site that can never be fixed.
-Edward
On Sat, Dec 5, 2015 at 5:38 PM, David Feuer
wrote: The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

If you aren't the one writing the code that can't be called you may never
see the warning. It'll be tucked away in a cabal or stack build log
somewhere.
-Edward
On Sun, Dec 6, 2015 at 12:06 AM, David Feuer
No, I want it to *warn* by default. If I write
foo :: something that will fail the ambiguity check bar = something that uses foo in a (necessarily) ambiguous way
the current default leads me to do this:
1. Attempt to compile. Get an ambiguity error on foo whose exact cause is hard for me to see. 2. Enable AllowAmbiguousTypes and recompile. Get an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 3. Fix foo, and disable AllowAmbiguousTypes.
I'd much rather go with
1. Attempt to compile. Get an ambiguity *warning* on foo whose exact cause is hard for me to see, but also an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 2. Fix foo.
Simple example of how it is currently:
let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:14:12: Couldn't match expected type ‘F a’ with actual type ‘F a0’ NB: ‘F’ is a type function, and may not be injective The type variable ‘a0’ is ambiguous In the ambiguity check for the type signature for ‘foo’: foo :: forall a. Num a => F a To defer the ambiguity check to use sites, enable AllowAmbiguousTypes In the type signature for ‘foo’: foo :: Num a => F a
Couldn't match what with what? Huh? Where did a0 come from?
:set -XAllowAmbiguousTypes let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:16:61: Couldn't match expected type ‘Int’ with actual type ‘F a0’ The type variable ‘a0’ is ambiguous In the expression: foo In an equation for ‘bar’: bar = foo
Aha! That's the problem! It doesn't know what a0 is! How can I tell it what a0 is? Oh! I can't, because foo doesn't give me a handle on it. Guess I have to fix foo.
I'd really, really like to get *both* of those messages in one go, with the first one preferably explaining itself a bit better.
So you are saying you want users to write a ton of code that happens to have signatures that can never be called and only catch it when they go to
actually use it in a concrete situation much later?
I don't really show how this would be a better default.
When and if users see the problem later they have to worry about if they are doing something wrong at the definition site or the call site. With the status quo it complains at the right time that you aren't going to sit
On Sat, Dec 5, 2015 at 11:51 PM, Edward Kmett
wrote: try to there flailing around trying to fix a call site that can never be fixed.
-Edward
On Sat, Dec 5, 2015 at 5:38 PM, David Feuer
wrote: The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a
lot
of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

OK, fine. Is there a way to make it an error, but keep checking the
rest of the module? My goal is *get both messages if possible*, within
a module. I'm not tied to any particular mechanism of doing so.
On Sun, Dec 6, 2015 at 12:13 AM, Edward Kmett
If you aren't the one writing the code that can't be called you may never see the warning. It'll be tucked away in a cabal or stack build log somewhere.
-Edward
On Sun, Dec 6, 2015 at 12:06 AM, David Feuer
wrote: No, I want it to *warn* by default. If I write
foo :: something that will fail the ambiguity check bar = something that uses foo in a (necessarily) ambiguous way
the current default leads me to do this:
1. Attempt to compile. Get an ambiguity error on foo whose exact cause is hard for me to see. 2. Enable AllowAmbiguousTypes and recompile. Get an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 3. Fix foo, and disable AllowAmbiguousTypes.
I'd much rather go with
1. Attempt to compile. Get an ambiguity *warning* on foo whose exact cause is hard for me to see, but also an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 2. Fix foo.
Simple example of how it is currently:
let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:14:12: Couldn't match expected type ‘F a’ with actual type ‘F a0’ NB: ‘F’ is a type function, and may not be injective The type variable ‘a0’ is ambiguous In the ambiguity check for the type signature for ‘foo’: foo :: forall a. Num a => F a To defer the ambiguity check to use sites, enable AllowAmbiguousTypes In the type signature for ‘foo’: foo :: Num a => F a
Couldn't match what with what? Huh? Where did a0 come from?
:set -XAllowAmbiguousTypes let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:16:61: Couldn't match expected type ‘Int’ with actual type ‘F a0’ The type variable ‘a0’ is ambiguous In the expression: foo In an equation for ‘bar’: bar = foo
Aha! That's the problem! It doesn't know what a0 is! How can I tell it what a0 is? Oh! I can't, because foo doesn't give me a handle on it. Guess I have to fix foo.
I'd really, really like to get *both* of those messages in one go, with the first one preferably explaining itself a bit better.
On Sat, Dec 5, 2015 at 11:51 PM, Edward Kmett
wrote: So you are saying you want users to write a ton of code that happens to have signatures that can never be called and only catch it when they go to try to actually use it in a concrete situation much later?
I don't really show how this would be a better default.
When and if users see the problem later they have to worry about if they are doing something wrong at the definition site or the call site. With the status quo it complains at the right time that you aren't going to sit there flailing around trying to fix a call site that can never be fixed.
-Edward
On Sat, Dec 5, 2015 at 5:38 PM, David Feuer
wrote: The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites are typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be possible to turn that into a warning by default?
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

That gets into making the whole parser / renamer / type checker a bit more
incremental, and while that would be awesome, and an excellent example of
that user experience can be seen in the lean theorem prover, its certainly
trickier to see how to realize it in Haskell because the order in the
module of top level decls has no bearing on what may be a mutually
recursive knot of definitions.
Likewise, while I definitely think that it's good to have the maximal set
of independent type errors reported back, this is the same type error just
deferred to a new location. Likewise, as ed notes, this would push a lot
of errors out of libraries and into library clients , which just seems bad
On Dec 6, 2015 12:15 AM, "David Feuer"
OK, fine. Is there a way to make it an error, but keep checking the rest of the module? My goal is *get both messages if possible*, within a module. I'm not tied to any particular mechanism of doing so.
If you aren't the one writing the code that can't be called you may never see the warning. It'll be tucked away in a cabal or stack build log somewhere.
-Edward
On Sun, Dec 6, 2015 at 12:06 AM, David Feuer
wrote: No, I want it to *warn* by default. If I write
foo :: something that will fail the ambiguity check bar = something that uses foo in a (necessarily) ambiguous way
the current default leads me to do this:
1. Attempt to compile. Get an ambiguity error on foo whose exact cause is hard for me to see. 2. Enable AllowAmbiguousTypes and recompile. Get an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 3. Fix foo, and disable AllowAmbiguousTypes.
I'd much rather go with
1. Attempt to compile. Get an ambiguity *warning* on foo whose exact cause is hard for me to see, but also an error on bar whose exact cause is completely obvious, and that makes it perfectly clear what I need to do to fix foo. 2. Fix foo.
Simple example of how it is currently:
let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:14:12: Couldn't match expected type ‘F a’ with actual type ‘F a0’ NB: ‘F’ is a type function, and may not be injective The type variable ‘a0’ is ambiguous In the ambiguity check for the type signature for ‘foo’: foo :: forall a. Num a => F a To defer the ambiguity check to use sites, enable
AllowAmbiguousTypes
In the type signature for ‘foo’: foo :: Num a => F a
Couldn't match what with what? Huh? Where did a0 come from?
:set -XAllowAmbiguousTypes let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo
<interactive>:16:61: Couldn't match expected type ‘Int’ with actual type ‘F a0’ The type variable ‘a0’ is ambiguous In the expression: foo In an equation for ‘bar’: bar = foo
Aha! That's the problem! It doesn't know what a0 is! How can I tell it what a0 is? Oh! I can't, because foo doesn't give me a handle on it. Guess I have to fix foo.
I'd really, really like to get *both* of those messages in one go, with the first one preferably explaining itself a bit better.
On Sat, Dec 5, 2015 at 11:51 PM, Edward Kmett
wrote: So you are saying you want users to write a ton of code that happens
to
have signatures that can never be called and only catch it when they go to try to actually use it in a concrete situation much later?
I don't really show how this would be a better default.
When and if users see the problem later they have to worry about if
are doing something wrong at the definition site or the call site. With
status quo it complains at the right time that you aren't going to sit there flailing around trying to fix a call site that can never be fixed.
-Edward
On Sat, Dec 5, 2015 at 5:38 PM, David Feuer
wrote: The ambiguity check produces errors that are quite surprising to the uninitiated. When the check is suppressed, the errors at use sites
are
typically much easier to grasp. On the other hand, there's obviously a lot of value to catching mistakes as soon as possible. Would it be
On Sun, Dec 6, 2015 at 12:13 AM, Edward Kmett
wrote: they the possible to turn that into a warning by default?
_______________________________________________ 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

| OK, fine. Is there a way to make it an error, but keep checking the
| rest of the module? My goal is *get both messages if possible*, within
| a module. I'm not tied to any particular mechanism of doing so.
Yes it'd be possible. A bit fiddly, but certainly possible.
Of course, doing so can lead to a cascade of other errors, but in this case you seem to actively want those follow-on errors.
Would you like to open a ticket with a few illustrative examples to motivate your proposal?
Simon
|
| On Sun, Dec 6, 2015 at 12:13 AM, Edward Kmett

Sure, I'll open the ticket. It may well turn out that there's a less
invasive way to accomplish my ultimate goal (more useful error messages for
ambiguous types) without allowing the cascade you're worried about. In
foo :: Num a => F a -> G a
Something more like the following would be much better than what we
currently get:
The type variable `a' in the type of `foo :: Num a => F a -> G a' is
ambiguous. This means that code attempting to use `foo' will not be able to
give it a signature determining `a'. In particular: `a' appears only as an
argument to the type families `F' and `G', which may not be injective.
Therefore a signature at the use site fixing `F a' and `G a' to particular
types will not fix `a' to a particular type.
On Dec 7, 2015 8:31 AM, "Simon Peyton Jones"
| OK, fine. Is there a way to make it an error, but keep checking the | rest of the module? My goal is *get both messages if possible*, within | a module. I'm not tied to any particular mechanism of doing so.
Yes it'd be possible. A bit fiddly, but certainly possible.
Of course, doing so can lead to a cascade of other errors, but in this case you seem to actively want those follow-on errors.
Would you like to open a ticket with a few illustrative examples to motivate your proposal?
Simon
| | On Sun, Dec 6, 2015 at 12:13 AM, Edward Kmett
| wrote: | > If you aren't the one writing the code that can't be called you may | > never see the warning. It'll be tucked away in a cabal or stack | build | > log somewhere. | > | > -Edward | > | > On Sun, Dec 6, 2015 at 12:06 AM, David Feuer | wrote: | >> | >> No, I want it to *warn* by default. If I write | >> | >> foo :: something that will fail the ambiguity check bar = something | >> that uses foo in a (necessarily) ambiguous way | >> | >> the current default leads me to do this: | >> | >> 1. Attempt to compile. Get an ambiguity error on foo whose exact | >> cause is hard for me to see. | >> 2. Enable AllowAmbiguousTypes and recompile. Get an error on bar | >> whose exact cause is completely obvious, and that makes it | perfectly | >> clear what I need to do to fix foo. | >> 3. Fix foo, and disable AllowAmbiguousTypes. | >> | >> I'd much rather go with | >> | >> 1. Attempt to compile. Get an ambiguity *warning* on foo whose | exact | >> cause is hard for me to see, but also an error on bar whose exact | >> cause is completely obvious, and that makes it perfectly clear what | I | >> need to do to fix foo. | >> 2. Fix foo. | >> | >> Simple example of how it is currently: | >> | >> > let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo | >> | >> <interactive>:14:12: | >> Couldn't match expected type ‘F a’ with actual type ‘F a0’ | >> NB: ‘F’ is a type function, and may not be injective | >> The type variable ‘a0’ is ambiguous | >> In the ambiguity check for the type signature for ‘foo’: | >> foo :: forall a. Num a => F a | >> To defer the ambiguity check to use sites, enable | AllowAmbiguousTypes | >> In the type signature for ‘foo’: foo :: Num a => F a | >> | >> Couldn't match what with what? Huh? Where did a0 come from? | >> | >> > :set -XAllowAmbiguousTypes | >> > let foo :: Num a => F a; foo = undefined; bar :: Int; bar = foo | >> | >> <interactive>:16:61: | >> Couldn't match expected type ‘Int’ with actual type ‘F a0’ | >> The type variable ‘a0’ is ambiguous | >> In the expression: foo | >> In an equation for ‘bar’: bar = foo | >> | >> Aha! That's the problem! It doesn't know what a0 is! How can I tell | >> it what a0 is? Oh! I can't, because foo doesn't give me a handle on | it. | >> Guess I have to fix foo. | >> | >> I'd really, really like to get *both* of those messages in one go, | >> with the first one preferably explaining itself a bit better. | >> | >> On Sat, Dec 5, 2015 at 11:51 PM, Edward Kmett | wrote: | >> > So you are saying you want users to write a ton of code that | >> > happens to have signatures that can never be called and only | catch | >> > it when they go to try to actually use it in a concrete situation | >> > much later? | >> > | >> > I don't really show how this would be a better default. | >> > | >> > When and if users see the problem later they have to worry about | if | >> > they are doing something wrong at the definition site or the call | >> > site. With the status quo it complains at the right time that you | >> > aren't going to sit there flailing around trying to fix a call | site | >> > that can never be fixed. | >> > | >> > -Edward | >> > | >> > On Sat, Dec 5, 2015 at 5:38 PM, David Feuer | | >> > wrote: | >> >> | >> >> The ambiguity check produces errors that are quite surprising to | >> >> the uninitiated. When the check is suppressed, the errors at use | >> >> sites are typically much easier to grasp. On the other hand, | >> >> there's obviously a lot of value to catching mistakes as soon as | >> >> possible. Would it be possible to turn that into a warning by | >> >> default? | >> >> | >> >> | >> >> _______________________________________________ | >> >> ghc-devs mailing list | >> >> ghc-devs@haskell.org | >> >> | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fma | >> >> il.haskell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs&data=01%7 | >> >> | c01%7csimonpj%40064d.mgd.microsoft.com%7c572fb4db692644c7b2d408d2f | >> >> | dfc50bb%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=tzknS1bYbEs2G | >> >> NPvXuu6o1st%2b2VMSTTmRSH1L%2f9BSsk%3d | >> >> | >> > | > | > | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.h | askell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc- | devs%0a&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c572fb4db6926 | 44c7b2d408d2fdfc50bb%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=kYhH | Q00HzSxbbNyqFt2OmHWSpPTyxsbeJPCF1tDzAA0%3d
participants (6)
-
Carter Schonwald
-
David Feuer
-
David Kraeutmann
-
Edward Kmett
-
Simon Peyton Jones
-
Sumit Sahrawat, Maths & Computing, IIT (BHU)