{-# LANGUAGE TypeFamilies #-} module Language.Symantic.Grammar.Source where -- * Class 'Gram_Meta' -- | Symantics for including metadata -- (like the position in the input) -- in the result of a grammar. class Gram_Meta meta g where withMeta :: g (meta -> a) -> g a -- * Class 'Source' class Source src where noSource :: src instance Source () where noSource = () -- * Class 'Inj_Source' class Source src => Inj_Source a src where inj_Source :: a -> src instance Inj_Source a () where inj_Source _ = () -- ** 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` source :: (Inj_Source src (SourceOf a), Sourced a) => a -> src -> a source a src = a `setSource` inj_Source src -- ** Type 'Text_of_Source' type family Text_of_Source (src :: *) :: * type instance Text_of_Source () = () withSource :: forall src g a. Gram_Meta (Text_of_Source src) g => Inj_Source (Text_of_Source src) src => Functor g => g (src -> a) -> g a withSource g = withMeta $ (\f (txt :: Text_of_Source src) -> f (inj_Source txt :: src)) <$> g -- * Type 'At' -- | Attach a source. data At src a = At src a deriving (Eq, Show) instance Functor (At src) where fmap f (At src a) = At src (f a) unAt :: At src a -> a unAt (At _ a) = a