#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 6 years ago by
Milestone: | 7.6.1 → 7.6.2 |
---|
comment:2 follow-up: 3 Changed 6 years ago by
comment:3 Changed 6 years ago by
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 6 years ago by
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 6 years ago by
Milestone: | 7.6.2 → 7.8.1 |
---|---|
Owner: | set to simonpj |
comment:6 Changed 5 years ago by
Cc: | hackage.haskell.org@… added |
---|
comment:7 Changed 4 years ago by
Milestone: | 7.8.3 → 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:9 Changed 4 years ago by
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 4 years ago by
Related Tickets: | → #8883 |
---|---|
Resolution: | → duplicate |
Status: | new → 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:12 Changed 4 years ago by
Test Case: | → 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.