content: {-# LANGUAGE DataKinds             #-}
  {-# LANGUAGE PolyKinds             #-}
  {-# LANGUAGE TypeFamilies          #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE FlexibleInstances     #-}
  
  {-|
    Module      :  Data.Arguments
    Copyright   :  (c) Matt Noonan 2018
    License     :  BSD-style
    Maintainer  :  matt.noonan@gmail.com
    Portability :  portable
  -}
  
  module Data.Arguments
    ( Argument(..)
    , LHS, RHS
    , Arg(..)
    , arg
    ) where
  
  -- | Get or modify a type within a larger type.
  --   This is entirely a type-level operation, there
  --   is nothing corresponding to a value access or update.
  class Argument (f :: k1) (n :: k2) where
    type GetArg f n   :: k
    type SetArg f n x :: k1
  
  -- | Position: the left-hand side of a type.
  data LHS
  
  -- | Position: the right-hand side of a type.
  data RHS
  
  instance Argument (Either a b) LHS where
    type GetArg (Either a b) LHS    = a
    type SetArg (Either a b) LHS a' = Either a' b
  
  instance Argument (Either a b) RHS where
    type GetArg (Either a b) RHS    = b
    type SetArg (Either a b) RHS b' = Either a b'
  
  -- | A specialized proxy for arguments.
  data Arg n = Arg
  
  -- | Inhabitant of the argument proxy.
  arg :: Arg n
  arg = Arg
  
  