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 |