I can use a type alias to add HasCallStack
to a monad e.g.:
type XIO' a = HasCallStack => IO a
which saves me some keystrokes and I don't have to remember about putting HasCallStack
everywhere.
However, when I define a custom datatype like that:
data XIO a = HasCallStack => XIO { unXIO :: IO a }
The call stacks aren't added to functions of type XIO
. Is there a way to add a HasCallStack
constraint automatically to a custom monad? I've also tried adding it to all functions in the instances using InstanceSigs
but it made no difference.
A full example:
module Main (main) where
import RIO
main :: IO ()
main = do
catchAny (unXIO $ f1) $ \ex -> do
putStrLn "::: An exception without callstack"
putStrLn $ displayException ex
catchAny (f1') $ \ex -> do
putStrLn "::: An exception with callstack"
putStrLn $ displayException ex
f1' :: XIO' ()
f1' = do
pure ()
f2'
pure ()
f1 :: XIO ()
f1 = do
pure ()
f2
pure ()
f2' :: XIO' ()
f2' = do
pure ()
_ <- throwIO $ stringException "Hello"
pure ()
f2 :: XIO ()
f2 = do
pure ()
_ <- throwIO $ stringException "Hello"
pure ()
type XIO' a = HasCallStack => IO a
data XIO a = HasCallStack => XIO { unXIO :: IO a }
instance Functor XIO where
fmap f (XIO m) = XIO $ fmap f m
instance Applicative XIO where
pure a = XIO $ pure a
XIO f <*> XIO a = XIO $ f <*> a
instance Monad XIO where
return = pure
XIO m >>= f = XIO $ m >>= (\k -> unXIO $ f k)
instance MonadIO XIO where
liftIO m = XIO $ m
I can use a type alias to add HasCallStack
to a monad e.g.:
type XIO' a = HasCallStack => IO a
which saves me some keystrokes and I don't have to remember about putting HasCallStack
everywhere.
However, when I define a custom datatype like that:
data XIO a = HasCallStack => XIO { unXIO :: IO a }
The call stacks aren't added to functions of type XIO
. Is there a way to add a HasCallStack
constraint automatically to a custom monad? I've also tried adding it to all functions in the instances using InstanceSigs
but it made no difference.
A full example:
module Main (main) where
import RIO
main :: IO ()
main = do
catchAny (unXIO $ f1) $ \ex -> do
putStrLn "::: An exception without callstack"
putStrLn $ displayException ex
catchAny (f1') $ \ex -> do
putStrLn "::: An exception with callstack"
putStrLn $ displayException ex
f1' :: XIO' ()
f1' = do
pure ()
f2'
pure ()
f1 :: XIO ()
f1 = do
pure ()
f2
pure ()
f2' :: XIO' ()
f2' = do
pure ()
_ <- throwIO $ stringException "Hello"
pure ()
f2 :: XIO ()
f2 = do
pure ()
_ <- throwIO $ stringException "Hello"
pure ()
type XIO' a = HasCallStack => IO a
data XIO a = HasCallStack => XIO { unXIO :: IO a }
instance Functor XIO where
fmap f (XIO m) = XIO $ fmap f m
instance Applicative XIO where
pure a = XIO $ pure a
XIO f <*> XIO a = XIO $ f <*> a
instance Monad XIO where
return = pure
XIO m >>= f = XIO $ m >>= (\k -> unXIO $ f k)
instance MonadIO XIO where
liftIO m = XIO $ m
Share
asked Mar 3 at 20:23
carbolymercarbolymer
1,6522 gold badges17 silver badges32 bronze badges
1
|
1 Answer
Reset to default 1I can't think of a way to associate the HasCallStack
constraint with a data type. Because of the way it's implemented, I think it needs to be part of each function signature that should contribute to the call stack, either specified directly or as part of a type alias.
So, your best bet is to define your custom monad as an internal type and then define a type alias for use in function signatures, like:
newtype XIO_internal a = XIO { unXIO :: IO a }
type XIO a = HasCallStack => XIO_internal a
For example:
import RIO
newtype XIO_internal a = XIO { unXIO :: IO a }
deriving (Functor, Applicative, Monad, MonadIO)
type XIO a = HasCallStack => XIO_internal a
main :: IO ()
main = do
catchAny (unXIO $ f1 2) $ \ex -> do
putStrLn $ displayException ex
f1 :: Int -> XIO ()
f1 x = do
f2 (x*2)
f2 :: Int -> XIO ()
f2 x = do
liftIO $ print x
_ <- throwIO $ stringException "Hello"
pure ()
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745073572a4609700.html
HasCallStack
s could likely cause memory leaks for code that recurses a lot. – danidiaz Commented Mar 3 at 20:30