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
SomeStuff
value 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 thef
argument if you don't need that.After that, we take
takeRep @a
which models the (reflected) type representation of our unknown typea
. We check whether that matches with the patternApp d _
, i.e. whether typea
is an application ofd
to something we don't care_
. If so, we check whetherd
is indeed the (reflected representation of) ourD
type constructor. Matching the result ofeqTypeRepl
againstJust HRefl
makes GHC assumea ~ D t
for some fresh type variablet
, which is what we want. After that, we can callf x
confirming 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: