unsafeCoerce#'s kind is not as liberal enough to inspect tag bits.
Inspecting dynamic pointer tagging bits cannot be done with unsafeCoerce# alone. You have to introduce an extra box:
import Foreign
import Unsafe.Coerce
import Data.Bits
data Box a = Box a
unsafeIsEvaluated :: a -> Bool
unsafeIsEvaluated a = unsafeCoerce (Box a) .&. (sizeOf (undefined :: Int) - 1) /= 0
To see this operation in action, see the 'speculation' package.
There is of course the unsafeCoerce# primop, but it can't change kinds:
unsafeCoerce# :: a -> b
However, if unsafeCoerce# was able to switch to an unboxed kind:
unsafeCoerce# :: forall (b :: ??). a -> b -- 1
this could be done in one fell swoop without the extra box.
unsafeIsEvaluated a = unsafeCoerce# a `and#` (sIZEOF_INT# -# 1#)
Of course, this is far from the most liberal type, but
unsafeCoerce# :: forall (a :: ??). (b :: ??) -> b -- 2
would allow conversion to and from addres-sized unboxed types, although it would likely be risky from a GC perspective.
and worse
unsafeCoerce# :: forall (a :: ??). (b :: ?) -> b -- 3
might also be possible, but the interpretation with coercing into an unboxed tuple doesn't make much sense.
But overall the type given by (1) above is the most permissive possible without potentially disastrous interpretation consequences.
Trac metadata
Trac field | Value |
---|---|
Version | 6.12.3 |
Type | FeatureRequest |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |