7 ms·
That error message is annoyingly weird but is more to do with tryhaskell.org than haskell itself. Lots of programming languages which have a strict type system
by seanhunter 7y ago
That error message is annoyingly weird but is more to do with tryhaskell.org than haskell itself. Lots of programming languages which have a strict type system (eg Rust) deliberately choose not to coerce types even when a type conversion would mostly work so the developer chooses the set of types that get used.
GHC is a little better.
GHCi, version 8.4.4: http://www.haskell.org/ghc/ :? for help
Prelude> (div 6 2) + 1.0
<interactive>:1:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 18 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- nicoburns 7y agoThe Rust error messages are much better though. This program: fn main() { println!("{}", (6 / 2) + 1.0); } fails to compile with the following error message: error[E0277]: cannot add a float to an integer --> src/main.rs:3:28 | 3 | println!("{}", (6 / 2) + 1.0); | ^ no implementation for `{integer} + {float}` | = help: the trait `std::ops::Add<{float}>` is not implemented for `{integer}`
- twic 7y agoThe crucial difference to Haskell is that this program: fn main() { println!("{}", 3 + 1.0); } Also fails with substantially the same error message. Rust is consistent that you can't add integers to floats. Haskell's looseness around numeric literals means that it isn't. Mind you, Rust does have that kind of looseness within the integers, so this: fn three() -> u8 { 3 } fn one() -> u16 { 1 } fn main() { println!("{}", 3 + 1); println!("{}", 3 + one()); println!("{}", three() + 1); println!("{}", three() + one()); } Fails to compile only on the last println.
- momentoftop 7y agoThis isn't about coercion, which Haskell doesn't have. These error messages arise because of Haskell's choice that numeric literals should be polymorphic values with a typeclass constraint, meaning I can make those literals evaluate to my own types by defining a few instances. The resultant headaches with error messages are just the usual ones you get when you combine this amount of ad-hoc polymorphism with global type inference. For teaching beginners, I very much question the amount of polymorphism in Haskell, and one floated idea has been to use a custom Prelude with much less of it for teaching purposes. Alternatively, I would probably just tell students to read an error like that as "you did something wrong." I would say the same for any student faced with a Java stack-trace showing how their null value threw an exception deep inside library code.
- Quekid5 7y ago> meaning I can make those literals evaluate to my own types by defining a few instances. If you're defining instances, you're already an "expert", so why are you defining instances that are "hostile" to your beginner students? If people in the ecosystem are defining hostile instances, you should probably just ask them to stop it...? EDIT: Also, isn't failing to compile the almost-optimal case? It certainly doesn't fail at runtime.
- momentoftop 7y agoThe beginner isn't defining the instances. But the experts want the flexibility to define such instances, and that means even beginner code can involve an unhelpful amount of polymorphism. This isn't the case in Rust, where literals are near enough monomorphic. There's a similar situation with the now classic: Prelude> length ['a','b'] 2 Prelude> length ('a','b') 1 Here, beginners are potentially being burned by the fact that "length" is polymorphic with the type: length :: Foldable f => f a -> Int which is not a type I want to explain to beginners. At the same time, as an expert, I want length to be polymorphic and don't want to sacrifice its polymorphism for the sake of beginners.
- Quekid5 7y ago