keeping RelaxedPolyRec as optional feature can help spotting infinite recursion
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.
Trac metadata
Trac field | Value |
---|---|
Version | 6.12.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler (Type checker) |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | ghc@henning-thielemann.de |
Operating system | |
Architecture |