Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#10166 closed bug (invalid)

GHCi: internal error: stg_ap_p_ret

Reported by: andreas.abel Owned by:
Priority: normal Milestone:
Component: GHCi Version: 7.8.4
Keywords: Cc: hvr
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


import Unsafe.Coerce
coerce = Unsafe.Coerce.unsafeCoerce

data Nat = Zero | Suc Nat

fromNat :: Nat -> Integer
fromNat Zero    = 0
fromNat (Suc l) = 1 + fromNat l

instance Show Nat where
  show l = show (fromNat l)

data Exp = Const Nat | Pred | App Exp Exp

eval :: Exp -> a
eval (Const n) = coerce n
eval e         = coerce $ evalP e
    evalP Pred Zero    = Zero
    evalP Pred (Suc n) = n
    evalP e    n       = evalA e n

    evalA (App f e)    = eval f (eval e)
    evalA _            = error "eval"

-- With type signature, result is 0 (wrong, should be 1)
-- Without type signature: internal error: stg_ap_p_ret
-- test :: Nat
test = eval $ App Pred $ Const $ Suc $ Suc Zero

-- main prints 0 should maybe print 1
main :: IO ()
main = print (coerce test :: Nat)

when evaluatiing test at the ghci prompt after loading, I get

<interactive>: internal error: stg_ap_p_ret
    (GHC version 7.8.3 for x86_64_unknown_linux)
    Please report this as a GHC bug:

Process haskell aborted (core dumped)

Change History (3)

comment:1 Changed 3 years ago by monoidal

Resolution: invalid
Status: newclosed

Letting X be a shortcut for Const (Suc (Suc Zero)), your program makes an evaluation step

eval (App Pred X) => coerce $ evalP (App Pred X)

and attempts to print this as a Nat, but evalP (App Pred X) is a function (evalP takes two arguments), that's an invalid coercion.

If you change your eval to

eval :: Exp -> a
eval (Const n) = coerce n
eval Pred      = coerce pr
eval (App f e) = coerce (eval f (eval e))

pr Zero = Zero
pr (Succ n) = n

then it works on my machine, but you should use Any for such tricks (

Last edited 3 years ago by monoidal (previous) (diff)

comment:2 Changed 3 years ago by simonpj

Yes, there's a reason that unsafeCoerce is called "unsafeCoerce" :-). Renaming it to coerce is arguably misleading, especially since Data.Coerce exports a guaranteed-sound function coerce!


comment:3 Changed 3 years ago by rwbarton

(And this is a task that GADTs are well-suited for, in place of unsafeCoerce.)

Note: See TracTickets for help on using tickets.