content: {-# LANGUAGE DefaultSignatures      #-}
  {-# LANGUAGE MultiParamTypeClasses  #-}
  {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE PatternSynonyms        #-}
  {-# LANGUAGE ViewPatterns           #-}
  
  {-|
    Module      :  Data.The
    Copyright   :  (c) Matt Noonan 2018
    License     :  BSD-style
    Maintainer  :  matt.noonan@gmail.com
    Portability :  portable
  -}
  
  module Data.The
    ( The(..)
    , pattern The
    ) where
  
  import Data.Coerce
  
  {-| A class for extracing "the" underlying value.
      'the' should ideally be a coercion from some
      @newtype@ wrap of @a@ back to @a@.
   
      For this common use case, in the module where
      @newtype New a = New a@ is defined, an instance
      of @The@ can be created with an empty definition:
  
  @
  newtype New a = New a
  instance The (New a) a
  @
  -}
  class The d a | d -> a where
    the :: d -> a
    default the :: Coercible d a => d -> a
    the = coerce
  
  {-| A view pattern for discarding the wrapper around
      a value.
  
  @
  f (The x) = expression x
  @
  
      is equivalent to
  
  @
  f x = let x' = the x in expression x'
  @
  -}
  pattern The :: The d a => a -> d
  pattern The x <- (the -> x)
  