7 ms·
I think the problem is not just subjectivity, but also that people often give strong opinions without examples. Here's an example about Haskell. Go to https://
by cousin_it 7y ago
I think the problem is not just subjectivity, but also that people often give strong opinions without examples.
Here's an example about Haskell. Go to https://tryhaskell.org https://tryhaskell.org and enter these:
3
div 6 2
3 + 1.0
(div 6 2) + 1.0
The first line returns 3, and so does the second line. The third line returns 4.0. The fourth line fails with this error:
No instance for (Show a0)
arising from a use of ‘show_M552168474310802709512215’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Show a => Show (Const a b)
-- Defined in ‘Control.Applicative’
instance Show a => Show (ZipList a)
-- Defined in ‘Control.Applicative’
instance Show GeneralCategory -- Defined in ‘Data.Char’
...plus 106 others
In the expression:
show_M552168474310802709512215
(let e_16210 = (div 6 2) + 1.0 in e_16210)
In an equation for ‘e_155216847431080270951221555216847431080270951221516210621016210’:
e_155216847431080270951221555216847431080270951221516210621016210
= show_M552168474310802709512215
(let e_16210 = (div 6 2) + 1.0 in e_16210)
In the expression:
(let
e_155216847431080270951221555216847431080270951221516210621016210
= show_M552168474310802709512215 (let ... in e_16210)
in
e_155
- chungus 7y agoDon't get me wrong here, I get what you're saying, but: In practice a beginner would figure out you can't just 'silently' add Integrals and Fractionals by checking the types with the ":t" command Prelude> :t (div 6 2) (div 6 2) :: Integral a => a Prelude> :t 1.0 1.0 :: Fractional t => t Bonus: there is a language extension which does you do this: https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/guide-to-ghc-extensions/basic-syntax-extensions#numdecimals https://www.schoolofhaskell.com/school/to-infinity-and-beyon... If your point was that the error messages could be nicer, I agree.
- lgas 7y agoThat's surprising since it's fairly straightforward. The type of `3` gets inferred as `Num a => a` because there's nothing to constrain it further. The type of `div 6 2` gets inferred as `Integral a => a` because the type of `div` is `Integral a => a -> a -> a`. The type of `3 + 1.0` gets inferred as `Fractional a => a` because of the decimal point. Then the same thing happens in the last statement so the type of the subexpression `(div 6 2)` (still) gets inferred to `Integral a => a` and the type of `1.0` (still) gets inferred to `Fractional a => a` because of the decimal point. So at that point you have an expression that's trying to add something constrained to being a whole number to something constrained to being a fractional number and that is ill typed because there is no type you could choose for the overall expression that would meet both sets of constraints. Edit: When I first replied there was text at the bottom of the message saying that no one could explain why this happens. My comment was addressing that portion of the original message. The behavior itself is not surprising for the same reasons.
- deleted 7y ago[deleted]
- mic47 7y agonote that ghci will give you much more comprehensible error message, than tryhaskell.org
- okasaki 7y agoGHCi 8.4.4 has a better error message: 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
- seanhunter 7y agoYou aren't Chris Okasaki by any chance? "Purely Functional Data Structures" is one of my favourite CS books btw. Just mind-expanding.
- seanhunter 7y agoThat 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.
- dunefox 7y agoBad error message. Solution: (fromInteger (div 6 2)) + 1.0