liveBook · Manning

Phantom type

As explained in Functional Design and Architecture: Examples in Haskell

A phantom type is a type parameter that appears in a type declaration but not in the runtime representation of its values.

A phantom type parameter appears in a type declaration but not in the runtime representation of its values. It carries compile-time identity without adding stored data. In a key–value database language, the phantom parameter `db` distinguishes databases while operations still use `ByteString` keys and values. section 11.1.2

Use phantom types to make otherwise similar interfaces harder to misuse:

  • Declare empty marker types such as `ValuesDB` and `AstroDB`, then associate each with a database name through a `DB` type class. section 11.1.2
  • Parameterize the database language as `KVDBL db`, so a computation intended for one database cannot be silently substituted for another. section 11.1.2
  • Select the marker explicitly with type applications such as `@ValuesDB` or with a direct type annotation. section 11.1.2
  • Apply the same technique to service APIs: an `api` parameter selects an HTTP or TCP type-class instance, although mismatched runtime channels can still require error handling. section 13.2.6
Listing 11.3 Basic string-based key–value database interface
type KVDBKey   = ByteString
type KVDBValue = ByteString
  
data KVDBF next where
  Save :: KVDBKey 
       -> KVDBValue
       -> (DBResult () -> next)
       -> KVDBF next
  Load :: KVDBKey
       -> (DBResult KVDBValue -> next)
       -> KVDBF next
  
type KVDBL db = Free KVDBF                             #1
  
save :: KVDBKey -> KVDBValue -> KVDBL db (DBResult ()) #2
load :: KVDBKey -> KVDBL db (DBResult KVDBValue)       #2

Inspect the minimal `KVDBL db` interface to see the phantom database parameter attached to a free-monad language whose values contain only keys, values, and results. section 11.1.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Explains marker types, type classes, and type applications, while stopping short of fully hiding runtime channel mismatches.
Examples
Uses `ValuesDB` and `AstroDB` markers plus `HttpAstroService` and `TcpAstroService` selectors.
What it assumes
Assumes familiarity with Haskell type declarations and type classes while introducing marker types through database and service interfaces.
What you can do after
Apply it via Haskell type applications and type classes to distinguish compatible-looking database or service computations.
How it connects
Connects phantom types with type classes, free monads, type applications, dependency inversion, and final tagless style.

Also explained in

Compare how 2 books explain phantom type →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.