parsonsmatt/annotated-exception

Natural `CallStack` support for `Annotation`

parsonsmatt opened this issue · 1 comments

The type AnnC is a constraint alias for Eq a, Show a, Typeable a.

The functionality of the library absolutely depends on Typeable a, but without anything else, then Annotation is "just" a Data.Dynamic.Dynamic value.

One of the most obviously useful types to have in there is CallStack, which we cannot put in a [Annotation] because it lacks a Show instance. I've filed a GHC issue requesting one, but it will be a while before that is resolved.

One possibility is to write special support for CallStack in castAnnotation that, if you're trying to cast out a CallStack, we look for a CallStackAnnotation instead. This is a bit gross but it completely solves the problem . . if you're using castAnnotation instead of cast directly on the underlying value.

Maybe what's really necessary here is to use an Exception-like subtyping hierarchy with a custom class for doing the conversion. Annotation is already morally equivalent to SomeException in that an Exception e is just a (Show a, Typeable a) value. Having toAnnotation and fromAnnotation as the main methods on the class would provide a neat entry point to this. Then we have:

class (Typeable a, Show a) => Annotation a where
    toAnnotation :: a -> SomeAnnotation
    fromAnnotation :: SomeAnnotation -> Maybe a

data SomeAnnotation where
  SomeAnnotation :: Annotation a => a -> SomeAnnotation

This doesn't help with CallStack because we don't have a Show instance for it, so we still can't write instance Annotation CallStack.

Eh, I think the easiest thing to do here is special-case on CallStack and forward to the newtype wrapper. That should simplify quite a lot of code. Eventually if CallStack gets a Show instance then we can drop all that machinery.