Experimenting with existential types. Seems to be a great way to get some type flexibility.
I'm hitting a problem with unboxing an existential type after I've wrapped it up. My code as follows:
{-# LANGUAGE ExistentialQuantification #-}
class Eq a => Blurb a
data BlurbBox = forall a . Blurb a => BlurbBox a
data Greek = Alpha | Beta deriving Eq
instance Blurb Greek
data English = Ay | Bee deriving Eq
instance Blurb English
box1 :: BlurbBox
box1 = BlurbBox Alpha
box2 :: BlurbBox
box2 = BlurbBox Ay
main = do
case box1 of
BlurbBox Alpha -> putStrLn "Alpha"
BlurbBox Beta -> putStrLn "Beta"
BlurbBox Ay -> putStrLn "Ay"
BlurbBox Bee -> putStrLn "Bee"
This code compiles up to main, then complains about the type of BlurbBox Alpha. How do I go about unboxing/unpacking an existential type?
Existential types, or 'existentials' for short, are a way of 'squashing' a group of types into one, single type. Existentials are part of GHC's type system extensions.
forall is something called "type quantifier", and it gives extra meaning to polymorphic type signatures (e.g. :: a , :: a -> b , :: a -> Int , ...). While normaly forall plays a role of the "universal quantifier", it can also play a role of the "existential quantifier" (depends on the situation).
Existentials in Swift allow defining a dynamic value conforming to a specific protocol. Using primary associated types, we can constrain existentials to certain boundaries. The Swift team introduced the any keyword to let developers explicitly opt-in to a performance impact that might otherwise not be visible.
Indeed, existential types can't be unpacked, because their whole point is that the code expecting an existential type must work absolutely the same way (in the sense of parametric polymorphism) regardless of with which exact type the existential type variable was instantiated.
You can understand that better by understanding that
data BlurbBox = forall a . Blurb a => BlurbBox a
gets translated to
type BlurbBox = forall b . (forall a . Blurb a => a -> b) -> b
that is, BlurbBox is something that, given a polymorphic function that works for absolutely all Blurbs, can be used to produce the result of applying that function to some (unknown) blurb.
Thus, similarly to how you can't write a function of type f :: a -> Int and have f String = 5 and f Bool = 3, you can't dispatch on the type of 'a' in a BlurbBox.
You might have a look at the chapter in TAPL on existential types. It describes the translation that I've provided.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With