Ehh... except the times it thinks I could do something with an extension, but it's not actually something I want to do.
Still, it's very nice to have the starting point, and I agree it's not a bad experience overall.
Edited to add an example:
Prelude> 1 2
<interactive>:1:1: error:
• Non type-variable argument in the constraint: Num (t1 -> t2)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall t1 t2. (Num t1, Num (t1 -> t2)) => t2
Prelude> :set -XFlexibleContexts
Prelude> 1 2
<interactive>:3:1: error:
• Could not deduce (Num t0)
from the context: (Num t, Num (t -> t1))
bound by the inferred type for ‘it’:
forall t t1. (Num t, Num (t -> t1)) => t1
at <interactive>:3:1-3
The type variable ‘t0’ is ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall t1 t2. (Num t1, Num (t1 -> t2)) => t2
Prelude> :set -XAllowAmbiguousTypes
Prelude> 1 2
<interactive>:5:1: error:
• No instance for (Num (Integer -> ())) arising from a use of ‘it’
(maybe you haven't applied a function to enough arguments?)
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
There's nothing wrong with enabling FlexibleContexts, but it's not going to solve your problem. You likely don't want AllowAmbiguousTypes on globally (though it's not as dangerous as it might sound). The final error message you get is the most useful, so going on this little journey isn't terrible, but it could have been short circuited if you took a beat to understand the extension it was asking for, and why it's being asked for in this context.Edited to add:
The problem with the above code, of course, is that I'm trying to apply the function 1 to the value 2, but 1 doesn't represent a function. But it could! Because the way number literals in Haskell are handled is much the same way as OverloadedStrings works - 5 is treated as (fromInteger 5) - and they have type (Num a => a), so that the context gets to pick which numeric type they're interpreted as.
As far as the language is concerned, I could make integer literals represent functions that (say) add that number to an input:
instance Num (Integer -> Integer) where
fromInteger n = (+ n)
...
... but that's not actually what I wanted. Almost certainly, it was a typo.