Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Existential Types

I'm trying to wrap my brain around Haskell's existential types, and my first example is a heterogeneous list of things that can be shown:

{-# LANGUAGE ExistentialQuantification #-}
data Showable = forall a. Show a => Showable a

showableList :: [Showable]
showableList = [Showable "frodo", Showable 1]

Now it seems to me that the next thing I would want to do is make Showable an instance of Show so that, for example, my showableList could be displayed in the repl:

instance Show Showable where
  show a = ...

The problem I am having is that what I really want to do here is call the a's underlying show implementation. But I'm having trouble referring to it:

instance Show Showable where
  show a = show a

picks out Showable's show method on the RHS which runs in circles. I tried auto-deriving Show, but that doesn't work:

data Showable = forall a. Show a => Showable a
  deriving Show

gives me:

Can't make a derived instance of `Show Showable':
  Constructor `Showable' does not have a Haskell-98 type
  Possible fix: use a standalone deriving declaration instead
In the data type declaration for `Showable'

I'm looking for someway to call the underlying Show::show implementation so that Showable does not have to reinvent the wheel.

like image 829
Ara Vartanian Avatar asked Aug 13 '11 13:08

Ara Vartanian


People also ask

What is 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.

What is existential type Swift?

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.

What does forall mean in Haskell?

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).


1 Answers

instance Show Showable where
   show (Showable a) = show a

show a = show a doesn't work as you realized because it recurses infinitely. If we try this without existential types we can see the same problem and solution

data D = D Int
instance Show D where show a = show a -- obviously not going to work

instance Show D where show (D a) = "D " ++ (show a) -- we have to pull out the underlying value to work with it
like image 128
Logan Capaldo Avatar answered Sep 20 '22 16:09

Logan Capaldo