Ticket #1454 (closed bug: invalid)

Opened 6 years ago

Last modified 5 years ago

Confusing or bug: :t and :i don't return same type

Reported by: iampure@… Owned by:
Priority: normal Milestone:
Component: GHCi Version: 6.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

:t <function> and :i <function> don't return the same type for complex types. Is this intentional?

If it's not, it's a bug. :i returns the more general type, btw.

Attachments

NotAnotherOne.hs Download (0.5 KB) - added by iampure@… 6 years ago.
:t => gget :: (MonadState? (Bar a b) m) => m b and :i => gget :: (Zork a b m) => m b

Change History

Changed 6 years ago by simonpj

Please give a concrete example!

Simon

Changed 6 years ago by iampure@…

I can understand this might be frustrating, but the example I have was so complex, that it would have taken ages to extract a good example for you. You might remember the previous example code I gave earlier. This is an order of magnitude more complex.

Just let this issue open and someday probably someone will create a reproducible case. It might also be possible to add assertions to a release and everytime :i is executed also run :t to see whether they match and when not return an internal error with a request to make a reproducible case.

Changed 6 years ago by Isaac Dupree

Playing around in ghci:

let f a b = b^a
:t f
f :: (Num a, Integral b) => b -> a -> a
:i f
f :: (Integral b, Num a) => b -> a -> a

which mean the same thing but are, oddly, different... is this an example, or related to one?

Changed 6 years ago by iampure@…

In the particular case I am referring to the two types were of the form: (Context cxt) => <more types> -> <sometype containing a type variable> -> <more types> this was for :t

, but :i derived a type that was of the form: (Context cxt) => <more types> -> Concretetype -> <more types>

So, your case is not an example of this. I hadn't seen the bug earlier, so it might only come up in really hairy code.

Changed 6 years ago by igloo

If you don't have a simple example then attaching the complex one (if it's not proprietary or anything) is better than nothing.

Changed 6 years ago by simonpj

Furthermore, even quoting verbatim what GHC says in the bad case is better than describing in words the kind of thing it says.

Concerning Isaac's example, this is entirely expected behaviour. :t typechecks an arbitrary expression. It happens to consist of a single variable in this case bue it could be anything at all. E.g.

Prelude> :t map (* 2)
map (* 2) :: (Num a) => [a] -> [a]

So GHC generates all the constraints arising from the expression and then abstracts over them. There's no reason for it to keep them in the same order, and it doesn't. Mabye this is what iampure (I wonder what your real name is) is tripping over?

Simon

Changed 6 years ago by iampure@…

"So GHC generates all the constraints arising from the expression and then abstracts over them. There's no reason for it to keep them in the same order, and it doesn't. Mabye this is what iampure (I wonder what your real name is) is tripping over?"

No, I am not tripping over this. It's exactly as I described in a comment above. (06/22/07 15:54:38)

Changed 6 years ago by simonpj

OK, so it's not that. Then I can't see how to make progress without more information. At the very least, can you show a screen dump of what you see, please?

Simon

Changed 6 years ago by iampure@…

  • severity changed from normal to minor

I don't have the code anymore that generated that. (I realize it would have been better to make a snapshot and put it aside for some time). I suggest you to stop spending time on this until someone(maybe me) puts a test case here. I set severity to minor, since that fits better.

Changed 6 years ago by igloo

  • status changed from new to closed
  • resolution set to worksforme

Please reopen this bug if you (anyone) finds a testcase.

Changed 6 years ago by iampure@…

  • status changed from closed to reopened
  • resolution worksforme deleted

Changed 6 years ago by iampure@…

:t => gget :: (MonadState? (Bar a b) m) => m b and :i => gget :: (Zork a b m) => m b

Changed 6 years ago by guest

  • priority changed from normal to high
  • severity changed from minor to major

Raising priority, because it's confusing for me what the type is that GHC will use internally.

Changed 6 years ago by simonmar

  • priority changed from high to normal

thanks for the feedback. BTW, the priority of a bug report is normally set by the GHC team, in contrast to "severity" which is set by the submitter. Also if you want to indicate that a bug is important to you, the convention is to add yourself to the CC list. More details here:

WorkingConventions#TheBugTracker

Changed 6 years ago by guest

  • severity changed from major to blocker

This has now become a blocker.

Changed 6 years ago by guest

  • severity changed from blocker to normal

This had little to do with the actual blocker, which is now resolved.

Changed 6 years ago by igloo

  • status changed from reopened to closed
  • resolution set to invalid

Here's a self-contained example:

{-# LANGUAGE UndecidableInstances,
             NoMonomorphismRestriction,
             MultiParamTypeClasses,
             FunctionalDependencies,
             FlexibleContexts,
             FlexibleInstances #-}

module Foo where

class (Monad m) => MonadState s m | m -> s where
    get :: m s
    put :: s -> m ()

data Bar a b = Bar a b

gget :: (Zork a b m) => m b
gget = do Bar a b <- get
          return b

class (MonadState (Bar a b) m) => Zork a b m | m -> a b where
instance (MonadState (Bar a b) m, Monad m) => Zork a b m where
$ ghci z.hs
GHCi, version 6.7.20070817: http://www.haskell.org/ghc/  :? for help
Loading package base ... linking ... done.
[1 of 1] Compiling Foo              ( z.hs, interpreted )
Ok, modules loaded: Foo.
*Foo> :i gget
gget :: (Zork a b m) => m b     -- Defined at z.hs:17:0-3
*Foo> :t gget
gget :: (MonadState (Bar a b) m) => m b
*Foo> 

This seems entirely reasonable to me. If you ask for info about the name gget then you get the type that you told the compiler it has. If you ask the compiler for the type of the expression gget, then when infering the type it uses the information from the instances that exist and the fundeps to infer the second type.

Note that if you comment out the type signature then GHC infers the second type for gget, and both :i and :t thus give that type:

*Foo> :i gget
gget :: (MonadState (Bar t1 t2) t) => t t2
        -- Defined at z.hs:17:0-3
*Foo> :t gget
gget :: (MonadState (Bar t1 t2) t) => t t2
*Foo> 

Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple

Changed 5 years ago by simonmar

  • os changed from Unknown to Unknown/Multiple
Note: See TracTickets for help on using tickets.