Ticket #3819 (closed proposal: fixed)

Opened 3 years ago

Last modified 3 years ago

keeping RelaxedPolyRec as optional feature can help spotting infinite recursion

Reported by: guest Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 6.12.1
Keywords: Cc: ghc@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

This is a ticket you have nothing to do about - isn't this great? I just want to give a real-world case where the current behaviour helped me to detect an infinite recursion early.

I wrote the following code, that implements a poke for any Traversable container with Storable elements:

   poke ::
      (Fold.Foldable f, Storable a) =>
      Ptr (f a) -> f a -> IO ()
   poke ptr x =
      evalStateT (Fold.traverse_ pokeState x) $
      castPtr ptr

   pokeState ::
      (Storable a) =>
      a -> StateT (Ptr a) IO ()
   pokeState x = do
      liftIO . flip poke x =<< get
      modify (flip advancePtr 1)

You can find this code here:

 http://code.haskell.org/~thielema/storable-record/src/Foreign/Storable/Traversable.hs

When I compiled this I got the compiler error:

   src/Foreign/Storable/Traversable.hs:67:0:
       Contexts differ in length
         (Use -XRelaxedPolyRec to allow this)
       When matching the contexts of the signatures for
         poke :: forall (f :: * -> *) a.
                 (Fold.Foldable f, Storable a) =>
                 Ptr (f a) -> f a -> IO ()
         pokeState :: forall a. (Storable a) => a -> StateT (Ptr a) IO ()
       The signature contexts in a mutually recursive group should all be identical
       When generalising the type(s) for poke, pokeState

This quickly pointed me to the problem, that the call to poke in pokeState actually was wrong. It must be Storable.poke. If GHC had compiled this, it would have certainly gone into an infinite recursion.

There are two ways to treat this example: * Blame my naming style where I re-use common identifiers and distinguish them later by qualification. * Count it as vote for keeping the RelaxedPolyRec? as optional feature.

Change History

Changed 3 years ago by guest

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

However ... when I enable RelaxedPolyRec?, the error is catched nevertheless:

    Couldn't match expected type `f a' against inferred type `a1'
    ...

I should change the proposal to "keep Haskell statically typed". :-)

Note: See TracTickets for help on using tickets.