{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeFamilies #-}
module Language.Symantic.Grammar.Source where

import Data.Functor (Functor)
import Data.Typeable (Typeable)

-- * Class 'Source'
class Source src where
	noSource :: src
instance Source () where
	noSource = ()

-- ** Class 'SourceInj'
class Source src => SourceInj a src where
	sourceInj :: a -> src
instance SourceInj a () where
	sourceInj _ = ()

-- ** Type family 'SourceOf'
type family SourceOf a

-- ** Type 'Sourced'
class Source (SourceOf a) => Sourced a where
	sourceOf  :: a -> SourceOf a
	setSource :: a -> SourceOf a -> a
infixl 5 `setSource`

withSource :: SourceInj src (SourceOf a) => Sourced a => a -> src -> a
withSource a src = a `setSource` sourceInj src

-- ** Type 'Source_Input'
type family Source_Input (src :: *) :: *
type instance Source_Input () = ()

-- ** Type 'Span'
data Span src
 =   Span
 {   spanBegin :: !src
 ,   spanEnd   :: !src
 } deriving (Eq, Ord, Show, Typeable)

-- ** Type 'At'
-- | Attach a 'Source' to something.
data At src a
 =   At
 {   at   :: !src
 ,   unAt :: !a
 } deriving (Eq, Functor, Ord, Show, Typeable)