#6022 closed bug (duplicate)
GHC infers over-general types
Reported by: | simonpj | Owned by: | simonpj |
---|---|---|---|
Priority: | normal | Milestone: | 7.10.1 |
Component: | Compiler | Version: | 7.4.1 |
Keywords: | Cc: | hackage.haskell.org@… | |
Operating System: | Unknown/Multiple | Architecture: | Unknown/Multiple |
Type of failure: | None/Unknown | Test Case: | typecheck/should_fail/T6022 |
Blocked By: | Blocking: | ||
Related Tickets: | #8883 | Differential Rev(s): | |
Wiki Page: |
Description
Consider
f x = x + head
GHC will (with no flags) will compile this almost-certainly-wrong program, giving f the type
f :: forall a. Num ([a] -> a) => ([a] -> a) -> [a] -> a
There's nothing wrong with that type, and in principle someone might later define a suitable instance of Num, but (a) it's not Haskell 98, and (b) it's unlikely to be right, so we've deferred a type error from the definition site of f to the (perhaps much later) call site.
I think GHC should complain, and require a type signature if that's what you really want. This came up on Stackoverflow
Change History (12)
comment:1 Changed 4 years ago by igloo
- Milestone changed from 7.6.1 to 7.6.2
comment:2 follow-up: ↓ 3 Changed 4 years ago by carter
comment:3 in reply to: ↑ 2 Changed 4 years ago by carter
fixed the formatting
Prelude> let g x = (+) x $ head Prelude> :t g
- g
- Num ([a] -> a) => ([a] -> a) -> [a] -> a
Prelude> let h x y = x + head y
Prelude> :t h
h : Num a => a -> [a] -> a
Prelude> let q x = (x +) . head
Prelude> :t q
q : Num c => c -> [c] -> c
comment:4 Changed 4 years ago by maeder
Why is this not Haskell 98? Well, hugs rejects this:
- Cannot infer instance *** Instance : Num ([a] -> a) *** Expression : f
But I don't know why, it works with "hugs -98". I cannot make ghc reject it, so ghc does not support Haskell 98!
In any case, I agree with "carter" that it should not be rejected (by default). If you ignore warnings like "no type signature" it is your own fault!
comment:5 Changed 4 years ago by igloo
- Milestone changed from 7.6.2 to 7.8.1
- Owner set to simonpj
comment:6 Changed 4 years ago by liyang
- Cc hackage.haskell.org@… added
comment:7 Changed 2 years ago by thoughtpolice
- Milestone changed from 7.8.3 to 7.10.1
Bumping priority down (these tickets haven't been closely followed or fixed in 7.4), and moving out to 7.10 and out of 7.8.3.
comment:8 Changed 2 years ago by thoughtpolice
- Priority changed from high to normal
Actually dropping priority. :)
comment:9 Changed 2 years ago by thomie
GHC should reject f without type signature, because it also rejects f with type signature, unless FlexibleContexts is enabled.
Prelude> let f x = x + head -- GHC should complain here Prelude> :t f f :: Num ([a] -> a) => ([a] -> a) -> [a] -> a Prelude> let f :: Num ([a] -> a) => ([a] -> a) -> [a] -> a; f x = x + head <interactive>:4:10: Non type-variable argument in the constraint: Num ([a] -> a) (Use FlexibleContexts to permit this) In the type signature for ‘f’: f :: Num ([a] -> a) => ([a] -> a) -> [a] -> a Prelude> :set -XFlexibleContexts Prelude> let f :: Num ([a] -> a) => ([a] -> a) -> [a] -> a; f x = x + head Prelude>
comment:10 Changed 2 years ago by thomie
- Resolution set to duplicate
- Status changed from new to closed
I now realize HEAD does exactly that, see #8883. I'm not sure if an extra regression test is needed, but here's what it would look like:
$ cat T6022.hs module T6022 where f x = x + head $ ghc-7.9.20141125 T6022.hs [1 of 1] Compiling T6022 ( T6022.hs, T6022.o ) T6022.hs:2:1: Non type-variable argument in the constraint: Num ([a] -> a) (Use FlexibleContexts to permit this) When checking that ‘f’ has the inferred type f :: forall a. Num ([a] -> a) => ([a] -> a) -> [a] -> a
comment:11 Changed 2 years ago by Simon Peyton Jones <simonpj@…>
comment:12 Changed 2 years ago by simonpj
- Test Case set to typecheck/should_fail/T6022
And the test was actually there, just marked as broken!
While this is likely wrong code, it is perfectly reasonable to have vector function num instances! (its not overly general, its just not pedagogically helpful for new people starting in haskell)
eg given Num a , the instance Num (Vector a -> a), has a perfectly natural (and useful) definition. and thus a Num instance for [a]-> a is reasonable too!
however, maybe an alternative approach would be add a suppressable warning for when a type class constraint is used which has no known instances?
here are example "similar ways" to write the same function, and their respective types, in ghci 7.6.1
Prelude> let g x = (+) x $ head Prelude> :t g g :: Num ([a] -> a) => ([a] -> a) -> [a] -> a
Prelude> let h x y = x + head y Prelude> :t h h :: Num a => a -> [a] -> a
Prelude> let q x = (x +) . head Prelude> :t q q :: Num c => c -> [c] -> c
so it seems that the core of the issue in the case of the bad example in this ticket is a syntactical one of making the intended composition. Likewise, I think this isn't a bug, the type checker is giving a type that the user can look at and see is "wrong" for their code!
i think rejecting code with that Num instance constraint would be bad. Unless someone has a counter point, I think this issue should be closed.