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

import Data.Eq (Eq)
import Data.Ord (Ord)
import Text.Show (Show)
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 'Sourceable'
class Source (SourceOf a) => Sourceable a where
        sourceOf  :: a -> SourceOf a
        setSource :: a -> SourceOf a -> a
infixl 5 `setSource`

withSource :: SourceInj src (SourceOf a) => Sourceable 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 'Sourced'
-- | Attach a 'Source' to something.
data Sourced src a
 =   Sourced
 {   atSource  :: !src
 ,   unSourced :: !a
 } deriving (Eq, Functor, Ord, Show, Typeable)