content: {-|
  Module: Squeal.PostgreSQL.Expression.Default
  Description: optional expressions
  Copyright: (c) Eitan Chatav, 2019
  Maintainer: eitan@morphism.tech
  Stability: experimental
  
  optional expressions
  -}
  
  {-# LANGUAGE
      DataKinds
    , GADTs
    , LambdaCase
    , OverloadedStrings
    , PatternSynonyms
    , PolyKinds
    , QuantifiedConstraints
    , RankNTypes
    , TypeOperators
  #-}
  
  module Squeal.PostgreSQL.Expression.Default
    ( -- * Default
      Optional (..)
    , mapOptional
    , pattern NotDefault
    ) where
  
  import Data.Kind
  import Generics.SOP
  
  import Squeal.PostgreSQL.Render
  import Squeal.PostgreSQL.Type.Schema
  
  -- | `Optional` is either `Default` or `Set`ting of a value,
  -- parameterized by an appropriate `Optionality`.
  data Optional (expr :: k -> Type) (ty :: (Optionality, k)) where
    -- | Use the `Default` value for a column.
    Default :: Optional expr ('Def :=> ty)
    -- | `Set` a value for a column.
    Set :: expr ty -> Optional expr (def :=> ty)
  
  instance (forall x. RenderSQL (expr x)) => RenderSQL (Optional expr ty) where
    renderSQL = \case
      Default -> "DEFAULT"
      Set x -> renderSQL x
  
  -- | Map a function over an `Optional` expression.
  mapOptional
    :: (expr x -> expr y)
    -> Optional expr (def :=> x)
    -> Optional expr (def :=> y)
  mapOptional f = \case
    Default -> Default
    Set x -> Set (f x)
  
  -- | `NotDefault` pattern analagous to `Just`.
  pattern NotDefault :: ty -> Optional I ('Def :=> ty)
  pattern NotDefault x = Set (I x)
  