liveBook · Manning

Existential type

As explained in Learn Haskell by Example

An existentially quantified type packages a value whose concrete type is hidden while exposing only operations guaranteed by specified constraints.

An existential type hides a value’s concrete type while preserving operations guaranteed by constraints. This allows values such as D Int and D Float to share one list, even though their type parameters differ. section 11.1.1

Use existential quantification when a container must accept different concrete types but expose a common capability:

  • Enable ExistentialQuantification and define a constructor such as MkE :: a -> E; every wrapped value then has type E. section 11.1.1
  • Add a constraint when consumers need to use the hidden value. ShowData can hide any Show value and still implement showThis. section 11.1.1
  • Define a capability-preserving instance for the wrapper, such as Pitchable Pitch delegating toFrequency to the wrapped pitch. section 11.1.2
  • Use standalone deriving when the existential wrapper needs a Show instance, and store differently typed values in ordinary lists. section 11.1.2

Heterogeneous pitches

A musical composition can wrap a chromatic pitch, a frequency, and a semitone value in one [Pitch] list. Although their representations differ, map toFrequency produces [440.0, 440.0, 440.0]. NoteStructure can then use Pitch without retaining its original type parameter. section 11.1.2

Exception packaging

SomeException packages any Exception instance behind an existential type. A handler can catch SomeFailure specifically, or accept SomeException to catch every exception, although broad handling is discouraged. section 14.4

ghci> data ShowData = forall a. (Show a) => ShowThis a
ghci> :{
ghci| showThis :: ShowData -> String
ghci| showThis (ShowThis x) = show x
ghci| :}
ghci> showValues = [ShowThis (1 :: Int), ShowThis ("Hi" :: String)]
ghci> :t showValues
showValues :: [ShowData]
ghci> map showThis showValues
["1","\"Hi\""]

Inspect a complete GHCi example that wraps Int and String values as ShowData and processes both through showThis. section 11.1.1

How Learn Haskell by Example covers it

How deep it goes
Demonstrates construction, constrained access, derived instances, delegation, and practical structures, while not detailing compiler internals.
Examples
Uses mixed Int and Float wrappers, ShowData values, musical pitches, NoteStructure, and SomeException handlers.
What it assumes
Assumes basic Haskell types, constructors, lists, and type classes; teaches hidden parameters and constrained access through examples.
What you can do after
Build it from scratch using constrained wrappers that store different concrete types while exposing a shared operation.
How it connects
Connects existential quantification to type classes, heterogeneous lists, GADTs, return-type polymorphism, and exceptions.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.