I have
data D t = ...
data SomeStuff = forall a (Typeable a, ...) => SomeStuff a
and at some point I get a SomeStuff whose internal a I'd like to try and cast to D t (where t can by any type, I'm only interested in the D part). Something which (in pseudo-Haskell) would look like:
case someStuff of
SomeStuff (_ :: a) -> case eqT :: Maybe (a :~: (exists t. D t)) of
Just Refl -> -- proven that `exists t. a ~ D t`
Nothing -> -- nothing to do here
I've been fiddling around with Data.Type.Equality and Type.Reflection (like App etc) and I can't get it to work. Anyone has a way to do that?
Testing whether the type is of the form
D _can be achieved exploitingType.Reflection, as follows.We start from giving some concrete definitions modeled on your example, so that we can test our code later on.
Then, we test for
D _as follows:Above, we take as arguments both the
SomeStuffvalue and a polymorphic functionf. The latter requires an argument of the formD _and is used here only to show that our approach actually works -- you can remove thefargument if you don't need that.After that, we take
takeRep @awhich models the (reflected) type representation of our unknown typea. We check whether that matches with the patternApp d _, i.e. whether typeais an application ofdto something we don't care_. If so, we check whetherdis indeed the (reflected representation of) ourDtype constructor. Matching the result ofeqTypeReplagainstJust HReflmakes GHC assumea ~ D tfor some fresh type variablet, which is what we want. After that, we can callf xconfirming GHC inferred the wanted type.As an alternative, we can exploit view patterns to make our code more compact, without sacrificing the readability too much: