-- | Data structures representing a set of datatypes to be folded. {-# LANGUAGE DeriveDataTypeable #-} module Data.Origami.Internal.FoldFamily( -- * Data structures FoldFamily(..), DataTy(..), DataCase(..), DataField(..), Ty(..), -- * Lenses HasName(..), dataCases, dataFields, dataTys, -- * Prisms _Atomic, _Nonatomic, _Funct, _Bifunct, _Trifunct, ) where import Control.Lens import Data.Data -- import qualified Data.Map as M import Language.Haskell.TH ------------------------------------------------------------ -- data ------------------------------------------------------------ -- | Represents a set of datatypes to be folded. newtype FoldFamily = FoldFamily [DataTy] deriving (Eq, Ord, Show, Data, Typeable) -- | Represents a datatype to be folded. data DataTy = DataTy Name [DataCase] deriving (Eq, Ord, Show, Data, Typeable) -- | Represents one way to construct a datatype; that is, one of its -- constructors and its arguments. data DataCase = DataCase Name [DataField] deriving (Eq, Ord, Show, Data, Typeable) -- | Represents a component of a datatype; that is, an argument to one -- of its constructors. data DataField = Atomic Ty -- ^ a type to be taken verbatim, not to be folded | Nonatomic Ty -- ^ a type to be recursively folded | Funct Name DataField -- ^ an application of a 'Functor' | Bifunct Name DataField DataField -- ^ an application of a 'Bifunctor' | Trifunct Name DataField DataField DataField -- ^ an application of a 'Trifunctor' deriving (Eq, Ord, Show, Data, Typeable) -- | Represents a datatype's name. newtype Ty = Ty Name deriving (Eq, Ord, Show, Data, Typeable) ------------------------------------------------------------ -- lenses ------------------------------------------------------------ -- | Access to the 'Name' of a Data structure class HasName d where name :: Lens' d Name -- | Access to the datatypes of a fold family. dataTys :: Iso' FoldFamily [DataTy] dataTys = iso (\ (FoldFamily dts) -> dts) FoldFamily {- -- | an 'Iso'' up to reordering foldFamilyMap :: Iso' FoldFamily (M.Map Name [DataCase]) foldFamilyMap = iso r l where r (FoldFamily dts) = M.fromList [ (nm, dcs) | DataTy nm dcs <- dts ] l m = FoldFamily [ DataTy nm dcs | (nm, dcs) <- M.toList m] -} instance HasName DataTy where name = lens (\ (DataTy nm _) -> nm) (\ (DataTy _ dcs) nm -> DataTy nm dcs) -- | Access to the 'DataCase's of a datatype dataCases :: Lens' DataTy [DataCase] dataCases = lens (\ (DataTy _ dcs) -> dcs) (\ (DataTy nm _) dcs -> DataTy nm dcs) instance HasName DataCase where name = lens (\ (DataCase nm _) -> nm) (\ (DataCase _ dfs) nm -> DataCase nm dfs) -- | Access to the 'DataFields's of a 'DataCase' dataFields :: Lens' DataCase [DataField] dataFields = lens (\ (DataCase _ dfs) -> dfs) (\ (DataCase nm _) dfs -> DataCase nm dfs) -- | Provides a 'Traversal' for an atomic 'Ty' in a 'DataField' _Atomic :: Prism' DataField Ty _Atomic = prism Atomic (\ df -> case df of Atomic ty -> Right ty _ -> Left df) -- | Provides a 'Traversal' for an nonatomic 'Ty' in a 'DataField' _Nonatomic :: Prism' DataField Ty _Nonatomic = prism Nonatomic (\ df -> case df of Nonatomic ty -> Right ty _ -> Left df) -- | Provides a 'Traversal' for a 'Functor' application in a 'DataField' _Funct :: Prism' DataField (Name, DataField) _Funct = prism (uncurry Funct) ( \ df -> case df of Funct nm df' -> Right (nm, df') _ -> Left df) -- | Provides a 'Traversal' for a 'Bifunctor' application in a 'DataField' _Bifunct :: Prism' DataField (Name, DataField, DataField) _Bifunct = prism (\ (nm, df, df') -> Bifunct nm df df') (\ df -> case df of Bifunct nm df' df'' -> Right (nm, df', df'') _ -> Left df) -- | Provides a 'Traversal' for a 'Trifunctor' application in a 'DataField' _Trifunct :: Prism' DataField (Name, DataField, DataField, DataField) _Trifunct = prism (\ (nm, df, df', df'') -> Trifunct nm df df' df'') (\ df -> case df of Trifunct nm df' df'' df''' -> Right (nm, df', df'', df''') _ -> Left df) instance HasName Ty where name = lens (\ (Ty nm) -> nm) (\ (Ty _) nm ->Ty nm)