GHC doesn't respect monomorphism restrictions for non-type-class-restricted values that are bound
Applicable in both 6.6.1 and 6.7.something.
This compiles as expected:
loop = read "foo"
int = show loop
req :: Int; req = loop
This fails to compile:
loop = undefined
int = show loop
req :: Int; req = loop
This compiles with -fmono-pat-binds (the default setting), but not with -fno-mono-pat-binds:
(loop) = undefined
int = show loop
req :: Int; req = loop
This compiles unless we use both -fno-mono-pat-binds and -fno-monomorphism-restriction, as expected:
(loop) = read "foo"
int = show loop
req :: Int; req = loop
loop=undefined versus loop=loop doesn't make any difference.
This compiles even with -fno-mono-pat-binds -fno-monomorphism-restriction. I don't understand how/why/how much 'case' makes a monomorphic binding:
x = case undefined of
loop -> let int = show loop; req :: Int; req = loop in ()
Admittedly, this is an odd case where the Report's rationales for the M-R <http://haskell.org/onlinereport/decls.html#sect4.5.4> aren't exactly applicable. "Rule 1 prevents computations from being unexpectedly repeated" -without typeclasses, no computations will be repeated. "Rule 1 prevents ambiguity" -well, true, but not in the strong way described by that point in the Report.
Encountered in the following, and I only recently figured out why it was not working.
{-# OPTIONS_GHC -fglasgow-exts -cpp #-}
{-# LANGUAGE CPP #-}
import Data.Typeable
#ifdef __GLASGOW_HASKELL__
import GHC.Prim ( unsafeCoerce# )
#endif
#ifdef __NHC__
import NonStdUnsafeCoerce (unsafeCoerce)
#endif
#ifdef __HUGS__
import Hugs.IOExts (unsafeCoerce)
#endif
#ifdef __GLASGOW_HASKELL__
unsafeCoerce :: a -> b
unsafeCoerce = unsafeCoerce#
#endif
data Dy = forall a. Dy !a !TypeRep
fromDyM :: Typeable a => Dy -> Maybe a
-- compiles:
fromDyM (Dy a typeRep) =
case unsafeCoerce a of
unsafeResult | typeRep == typeOf unsafeResult -> Just unsafeResult
| otherwise -> Nothing
--fails to compile:
fromDyM (Dy a typeRep) = result
where
unsafeResult = unsafeCoerce a
--(unsafeResult) = unsafeCoerce a --works because of mono-pat-binds
--unsafeResult = unsafeCoerce a `asTypeOfMaybe` result --was my earlier "fix"
result | typeRep == typeOf unsafeResult = Just unsafeResult
| otherwise = Nothing
asTypeOfMaybe :: a -> Maybe a -> a
asTypeOfMaybe a b = a
Testing the above examples in Hugs seems to be useless because Hugs's monomorphism is totally broken (it tries to find the monomorphic type too early in a way that depends on what order the declarations are in).
Trac metadata
Trac field | Value |
---|---|
Version | 6.6.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | Unknown |
Architecture | Unknown |