The following is a simplification of a pretty common pattern we have, where you have some retry combinator wrapping an IO operation. I would like to have some stack traces so I added the HasCallStack constraint but the resulting stacktrace was not really satisfactory:
import Control.Monad (forM_)
import GHC.Stack
httpCall :: HasCallStack => IO ()
httpCall = do
putStrLn $ prettyCallStack callStack
print "http resolved"
retry :: HasCallStack => IO () -> IO ()
retry op =
forM_ [1] $ \i ->
op
main :: IO ()
main = retry httpCall
stacktrace:
CallStack (from HasCallStack):
httpCall, called at main.hs:16:14 in main:Main
"http resolved"
I assumed the HasCallStack constraint gets resolved in main to fit the argument type of retry so I added the constraint to the argument type:
{-# LANGUAGE RankNTypes #-}
import Control.Monad (forM_)
import GHC.Stack
httpCall :: HasCallStack => IO ()
httpCall = do
putStrLn $ prettyCallStack callStack
print "http resolved"
retry :: HasCallStack => (HasCallStack => IO()) -> IO () -- NOTICE the constraint in the argument
retry op =
forM_ [1] $ \i ->
op
main :: IO ()
main = retry httpCall
Now the stacktrace has 2 more entries both of them quite surprising:
CallStack (from HasCallStack):
httpCall, called at main.hs:17:14 in main:Main
op, called at main.hs:14:5 in main:Main
retry, called at main.hs:17:8 in main:Main
"http resolved"
Problems
httpCallreports it was called frommain(line 17)opreports the correct line but is quite unexpected to see it in the stacktrace to begin with.
I expected something along the lines of:
CallStack (from HasCallStack):
httpCall, called at main.hs:14:5 in main:Main
retry, called at main.hs:17:8 in main:Main
"http resolved"
opandhttpCallare not functions, so GHC has to decide where is the "call point", the point where the "call" is logged into the stack trace. This is where the constraint is resolved by type inference, which might be not so intuitive. Consider to disambiguate this by havinghttpCall :: HasCallStack => () -> IO (), just for the sake of experimenting, and see if the result is more intuitive. - chi