th-typegraph 0.23 → 0.24
raw patch · 18 files changed
+629/−616 lines, 18 filesdep −memoize
Dependencies removed: memoize
Files
- Language/Haskell/TH/TypeGraph/Arity.hs +32/−0
- Language/Haskell/TH/TypeGraph/Edges.hs +7/−6
- Language/Haskell/TH/TypeGraph/Expand.hs +26/−58
- Language/Haskell/TH/TypeGraph/Free.hs +3/−23
- Language/Haskell/TH/TypeGraph/Graph.hs +0/−263
- Language/Haskell/TH/TypeGraph/HasState.hs +45/−0
- Language/Haskell/TH/TypeGraph/Info.hs +0/−192
- Language/Haskell/TH/TypeGraph/Prelude.hs +0/−7
- Language/Haskell/TH/TypeGraph/Shape.hs +1/−1
- Language/Haskell/TH/TypeGraph/Stack.hs +6/−4
- Language/Haskell/TH/TypeGraph/TypeGraph.hs +264/−0
- Language/Haskell/TH/TypeGraph/TypeInfo.hs +199/−0
- Language/Haskell/TH/TypeGraph/Unsafe.hs +0/−24
- Language/Haskell/TH/TypeGraph/Vertex.hs +3/−3
- test/Common.hs +8/−7
- test/TypeGraph.hs +19/−13
- test/Values.hs +2/−2
- th-typegraph.cabal +14/−13
+ Language/Haskell/TH/TypeGraph/Arity.hs view
@@ -0,0 +1,32 @@+-- | Function to compute the arity or kind of a Type, the number of+-- type parameters that need to be applied to get a concrete type.+module Language.Haskell.TH.TypeGraph.Arity+ ( typeArity+ ) where++import Language.Haskell.TH+import Language.Haskell.TH.Desugar ({- instances -})+import Language.Haskell.TH.Syntax (Quasi(qReify))+import Language.Haskell.TH.TypeGraph.Prelude (pprint')++-- | Compute the arity of a type - the number of type parameters that+-- must be applied to it in order to obtain a concrete type. I'm not+-- quite sure I understand the relationship between this and 'freeTypeVars'.+typeArity :: Quasi m => Type -> m Int+typeArity (ForallT _ _ typ) = typeArity typ -- Shouldn't a forall affect the arity?+typeArity ListT = return 1+typeArity (TupleT n) = return n+typeArity (VarT _) = return 1+typeArity (AppT t _) = typeArity t >>= \ n -> return $ n - 1+typeArity (ConT name) = qReify name >>= infoArity+ where+ infoArity (TyConI dec) = decArity dec+ infoArity (PrimTyConI _ _ _) = return 0+ infoArity (FamilyI dec _) = decArity dec+ infoArity info = error $ "typeArity - unexpected: " ++ pprint' info+ decArity (DataD _ _ vs _ _) = return $ length vs+ decArity (NewtypeD _ _ vs _ _) = return $ length vs+ decArity (TySynD _ vs t) = typeArity t >>= \ n -> return $ n + length vs+ decArity (FamilyD _ _ vs _mk) = return $ {- not sure what to do with the kind mk here -} length vs+ decArity dec = error $ "decArity - unexpected: " ++ show dec+typeArity typ = error $ "typeArity - unexpected type: " ++ show typ
Language/Haskell/TH/TypeGraph/Edges.hs view
@@ -35,6 +35,7 @@ import Control.Monad (filterM) import Control.Monad.Reader (MonadReader) import Control.Monad.State (execStateT, modify, StateT)+import Control.Monad.Trans (lift) import Data.Foldable import Data.List as List (filter, intercalate, map) import Data.Map as Map ((!), alter, delete, filterWithKey, fromList, keys, lookup, map, Map, mapKeysWith, mapWithKey)@@ -45,8 +46,9 @@ import Language.Haskell.TH -- (Con, Dec, nameBase, Type) import Language.Haskell.TH.PprLib (ptext) import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType)-import Language.Haskell.TH.TypeGraph.Info (TypeInfo, infoMap, typeSet, allVertices, fieldVertex, typeVertex')+import Language.Haskell.TH.TypeGraph.HasState (HasState) import Language.Haskell.TH.TypeGraph.Prelude (pprint')+import Language.Haskell.TH.TypeGraph.TypeInfo (TypeInfo, infoMap, typeSet, allVertices, fieldVertex, typeVertex') import Language.Haskell.TH.TypeGraph.Vertex (TGV, TGVSimple, vsimple) import Language.Haskell.TH.Desugar as DS (DsMonad) import Language.Haskell.TH.Instances ()@@ -58,10 +60,9 @@ -- fields, build and return the GraphEdges relation on TypeGraphVertex. -- This is not a recursive function, it stops when it reaches the field -- types.-typeGraphEdges :: forall m. (DsMonad m, Functor m, MonadReader TypeInfo m) =>- m (GraphEdges TGV)+typeGraphEdges :: forall m. (DsMonad m, Functor m, MonadReader TypeInfo m, HasState (Map Type (E Type)) m) => m (GraphEdges TGV) typeGraphEdges = do- execStateT (view typeSet >>= mapM_ (\t -> expandType t >>= doType)) mempty+ execStateT (view typeSet >>= mapM_ (\t -> lift (expandType t) >>= doType)) mempty where doType :: E Type -> StateT (GraphEdges TGV) m () doType typ = do@@ -98,8 +99,8 @@ -- Connect the vertex for this record type to one particular field vertex doField :: DsMonad m => Set TGV -> Name -> Name -> Either Int Name -> Type -> StateT (GraphEdges TGV) m () doField vs tname cname fld ftyp = do- v2 <- expandType ftyp >>= fieldVertex (tname, cname, fld)- v3 <- expandType ftyp >>= typeVertex'+ v2 <- lift (expandType ftyp) >>= fieldVertex (tname, cname, fld)+ v3 <- lift (expandType ftyp) >>= typeVertex' edge v2 v3 mapM_ (flip edge v2) vs -- Here's where we don't recurse, see?
Language/Haskell/TH/TypeGraph/Expand.hs view
@@ -22,82 +22,50 @@ {-# LANGUAGE TemplateHaskell #-} module Language.Haskell.TH.TypeGraph.Expand- ( Expanded(markExpanded, runExpanded')- , runExpanded+ ( E(E, unE)+ , ExpandMap , expandType , expandPred , expandClassP- , E(E) ) where -#if __GLASGOW_HASKELL__ < 709-import Control.Applicative-#endif-import Data.Function.Memoize (deriveMemoizable, memoize)+-- import Data.Function.Memoize (deriveMemoizable, memoize)+import Data.Map as Map (Map, lookup, insert) import Language.Haskell.Exts.Syntax () import Language.Haskell.TH import Language.Haskell.TH.Desugar as DS (DsMonad, dsType, expand, typeToTH) import Language.Haskell.TH.Instances () import Language.Haskell.TH.Syntax -- (Lift(lift))+import Language.Haskell.TH.TypeGraph.HasState (HasState(getState, modifyState)) import Prelude hiding (pred) -$(deriveMemoizable ''Type)-$(deriveMemoizable ''Name)-$(deriveMemoizable ''TyLit)-$(deriveMemoizable ''NameFlavour)-$(deriveMemoizable ''OccName)-$(deriveMemoizable ''NameSpace)-$(deriveMemoizable ''TyVarBndr)-$(deriveMemoizable ''ModName)-$(deriveMemoizable ''PkgName)+-- | A concrete type used to mark type which have been expanded+newtype E a = E {unE :: a} deriving (Eq, Ord, Show) --- | This class lets us use the same expand* functions to work with--- specially marked expanded types or with the original types.-class Expanded un ex | ex -> un where- markExpanded :: un -> ex -- ^ Unsafely mark a value as expanded- runExpanded' :: ex -> un -- ^ Strip mark off an expanded value+instance Ppr a => Ppr (E a) where+ ppr (E x) = ppr x +instance Lift (E Type) where+ lift etype = [|E $(lift (unE etype))|]++-- | The state type used to memoize expansions.+type ExpandMap = Map Type (E Type)+ -- | Apply the th-desugar expand function to a 'Type' and mark it as expanded.-expandType :: (DsMonad m, Expanded Type e) => Type -> m e-expandType = memoize $ \typ -> markExpanded <$> DS.typeToTH <$> (DS.dsType typ >>= DS.expand)+expandType :: (DsMonad m, HasState ExpandMap m) => Type -> m (E Type)+expandType typ = do+ getState >>= maybe expandType' return . Map.lookup typ+ where+ expandType' =+ do e <- E <$> DS.typeToTH <$> (DS.dsType typ >>= DS.expand)+ modifyState (Map.insert typ e)+ return e -- | Apply the th-desugar expand function to a 'Pred' and mark it as expanded. -- Note that the definition of 'Pred' changed in template-haskell-2.10.0.0.-expandPred :: (DsMonad m, Expanded Pred e) => Pred -> m e-#if __GLASGOW_HASKELL__ >= 709+expandPred :: (DsMonad m, HasState ExpandMap m) => Type -> m (E Type) expandPred = expandType-#else-expandPred (ClassP className typeParameters) = expandClassP className typeParameters-expandPred (EqualP type1 type2) = markExpanded <$> (EqualP <$> (runExpanded <$> expandType type1) <*> (runExpanded <$> expandType type2))-#endif -- | Expand a list of 'Type' and build an expanded 'ClassP' 'Pred'.-expandClassP :: forall m e. (DsMonad m, Expanded Pred e) => Name -> [Type] -> m e-expandClassP className typeParameters =-#if __GLASGOW_HASKELL__ >= 709- (expandType $ foldl AppT (ConT className) typeParameters) :: m e-#else- (markExpanded . ClassP className . map runExpanded) <$> mapM expandType typeParameters-#endif--runExpanded :: Expanded a (E a) => E a -> a-runExpanded = runExpanded'---- | A concrete type for which Expanded instances are declared below.-newtype E a = E a deriving (Eq, Ord, Show)--instance Expanded Type (E Type) where- markExpanded = E- runExpanded' (E x) = x--#if __GLASGOW_HASKELL__ < 709-instance Expanded Pred (E Pred) where- markExpanded = E- runExpanded' (E x) = x-#endif--instance Ppr a => Ppr (E a) where- ppr (E x) = ppr x--instance Lift (E Type) where- lift etype = [|markExpanded $(lift (runExpanded etype))|]+expandClassP :: forall m. (DsMonad m, HasState ExpandMap m) => Name -> [Type] -> m (E Type)+expandClassP className typeParameters = (expandType $ foldl AppT (ConT className) typeParameters) :: m (E Type)
Language/Haskell/TH/TypeGraph/Free.hs view
@@ -1,7 +1,9 @@+-- | Function to compute free type variable set for a Type. (I took+-- this from somewhere, I really need to credit it. Now when I search+-- all I can find is myself.) {-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, ScopedTypeVariables, TemplateHaskell #-} module Language.Haskell.TH.TypeGraph.Free ( freeTypeVars- , typeArity ) where import Control.Lens hiding (Strict, cons)@@ -21,28 +23,6 @@ st0 = St {_result = empty, _stack = empty} $(makeLenses ''St)---- | Compute the arity of a type - the number of type parameters that--- must be applied to it in order to obtain a concrete type. I'm not--- quite sure I understand the relationship between this and 'freeTypeVars'.-typeArity :: Quasi m => Type -> m Int-typeArity (ForallT _ _ typ) = typeArity typ -- Shouldn't a forall affect the arity?-typeArity ListT = return 1-typeArity (TupleT n) = return n-typeArity (VarT _) = return 1-typeArity (AppT t _) = typeArity t >>= \ n -> return $ n - 1-typeArity (ConT name) = qReify name >>= infoArity- where- infoArity (TyConI dec) = decArity dec- infoArity (PrimTyConI _ _ _) = return 0- infoArity (FamilyI dec _) = decArity dec- infoArity info = error $ "typeArity - unexpected: " ++ pprint' info- decArity (DataD _ _ vs _ _) = return $ length vs- decArity (NewtypeD _ _ vs _ _) = return $ length vs- decArity (TySynD _ vs t) = typeArity t >>= \ n -> return $ n + length vs- decArity (FamilyD _ _ vs _mk) = return $ {- not sure what to do with the kind mk here -} length vs- decArity dec = error $ "decArity - unexpected: " ++ show dec-typeArity typ = error $ "typeArity - unexpected type: " ++ show typ -- | Return the names of the type variables that are free in x. I.e., -- type variables that appear in the type expression but are not bound
− Language/Haskell/TH/TypeGraph/Graph.hs
@@ -1,263 +0,0 @@--- | Abstract operations on Maps containing graph edges.--{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE TypeFamilies #-}--module Language.Haskell.TH.TypeGraph.Graph- ( TypeGraph, typeInfo, edges, graph, gsimple, stack- , graphFromMap-- , allLensKeys- , allPathKeys- , allPathStarts- , reachableFrom- , reachableFromSimple- , goalReachableFull- , goalReachableSimple- , goalReachableSimple'-- , makeTypeGraph- , VertexStatus(..)- , typeGraphEdges'- , adjacent- , typeGraphVertex- , typeGraphVertexOfField- ) where--#if __GLASGOW_HASKELL__ < 709-import Control.Applicative-import Data.Monoid (mempty)-#else-import Control.Applicative-#endif-import Control.Lens -- (makeLenses, over, view)-import Control.Monad (when)-import Control.Monad.Reader (ask, local, MonadReader, ReaderT, runReaderT)-import Control.Monad.State (execStateT, modify, StateT)-import Control.Monad.Trans (lift)-import Data.Default (Default(def))-import Data.Foldable as Foldable-import Data.Graph hiding (edges)-import Data.List as List (map)-import Data.Map as Map (alter, fromList, fromListWith, Map, update)-import qualified Data.Map as Map (toList)-import Data.Maybe (fromJust, mapMaybe)-import Data.Set.Extra as Set (empty, fromList, insert, map, member, Set, singleton, toList, union, unions)-import Data.Traversable as Traversable-import Language.Haskell.Exts.Syntax ()-import Language.Haskell.TH-import Language.Haskell.TH.Desugar (DsMonad)-import Language.Haskell.TH.Instances ()-import Language.Haskell.TH.PprLib (ptext)-import Language.Haskell.TH.Syntax (Quasi(..))-import Language.Haskell.TH.TypeGraph.Edges (GraphEdges, simpleEdges)-import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType)-import Language.Haskell.TH.TypeGraph.Info (startTypes, TypeInfo, typeVertex', fieldVertex)-import Language.Haskell.TH.TypeGraph.Prelude (HasSet(getSet, modifySet), adjacent', reachable')-import Language.Haskell.TH.TypeGraph.Stack (HasStack(withStack, push), StackElement(StackElement))-import Language.Haskell.TH.TypeGraph.Vertex (TGV, TGVSimple, vsimple, TypeGraphVertex, etype)-import Prelude hiding (any, concat, concatMap, elem, exp, foldr, mapM_, null, or)--instance Ppr Vertex where- ppr n = ptext ("V" ++ show n)---- | Build a graph from the result of typeGraphEdges, each edge goes--- from a type to one of the types it contains. Thus, each edge--- represents a primitive lens, and each path in the graph is a--- composition of lenses.-graphFromMap :: forall key. (Ord key) =>- GraphEdges key -> (Graph, Vertex -> ((), key, [key]), key -> Maybe Vertex)-graphFromMap mp =- graphFromEdges triples- where- triples :: [((), key, [key])]- triples = List.map (\ (k, ks) -> ((), k, Foldable.toList ks)) $ Map.toList mp--data TypeGraph- = TypeGraph- { _typeInfo :: TypeInfo- , _edges :: GraphEdges TGV- , _graph :: (Graph, Vertex -> ((), TGV, [TGV]), TGV -> Maybe Vertex)- , _gsimple :: (Graph, Vertex -> ((), TGVSimple, [TGVSimple]), TGVSimple -> Maybe Vertex)- , _stack :: [StackElement]- }--$(makeLenses ''TypeGraph)--instance Monad m => HasStack (ReaderT TypeGraph m) where- withStack f = ask >>= f . view stack- push fld con dec action = local (stack %~ (\s -> StackElement fld con dec : s)) action--allPathStarts :: forall m. (DsMonad m, MonadReader TypeGraph m) => m (Set TGV)-allPathStarts = do- -- (g, vf, kf) <- graphFromMap <$> view edges- (g, vf, kf) <- view graph- kernel <- view typeInfo >>= \ti -> runReaderT (Traversable.mapM expandType (view startTypes ti) >>= Traversable.mapM typeVertex') ti- let keep = Set.fromList $ concatMap (reachable g) (mapMaybe kf kernel)- keep' = Set.map (view _2) . Set.map vf $ keep- return keep'---- | Lenses represent steps in a path, but the start point is a type--- vertex and the endpoint is a field vertex.-allLensKeys :: (DsMonad m, MonadReader TypeGraph m) => m (Map TGVSimple (Set TGV))-allLensKeys = do- g <- view graph- gs <- view gsimple- allPathStarts >>= return . Map.fromListWith Set.union . List.map (\x -> (view vsimple x, Set.fromList (adjacent' g x))) . Set.toList---- | Paths go between simple types.-allPathKeys :: (DsMonad m, MonadReader TypeGraph m) => m (Map TGVSimple (Set TGVSimple))-allPathKeys = do- gs <- view gsimple- allPathStarts >>= return . Map.fromList . List.map (\x -> (x, Set.fromList (reachable' gs x))) . Set.toList . Set.map (view vsimple)--reachableFrom :: forall m. (DsMonad m, MonadReader TypeGraph m) => TGV -> m (Set TGV)-reachableFrom v = do- -- (g, vf, kf) <- graphFromMap <$> view edges- (g, vf, kf) <- view graph- case kf v of- Nothing -> return Set.empty- Just v' -> return $ Set.map (\(_, key, _) -> key) . Set.map vf $ Set.fromList $ reachable (transposeG g) v'--reachableFromSimple :: forall m. (DsMonad m, MonadReader TypeGraph m) => TGVSimple -> m (Set TGVSimple)-reachableFromSimple v = do- -- (g, vf, kf) <- graphFromMap <$> view edges- (g, vf, kf) <- view gsimple- case kf v of- Nothing -> return Set.empty- Just v' -> return $ Set.map (\(_, key, _) -> key) . Set.map vf $ Set.fromList $ reachable (transposeG g) v'---- | Can we reach the goal type from the start type in this key?-goalReachableFull :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGV -> TGV -> m Bool-goalReachableFull gkey key0 = isReachable gkey key0 <$> view graph--goalReachableSimple :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGVSimple -> TGVSimple -> m Bool-goalReachableSimple gkey key0 = isReachable gkey key0 <$> view gsimple--goalReachableSimple' :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGV -> TGV -> m Bool-goalReachableSimple' gkey key0 = isReachable (view vsimple gkey) (view vsimple key0) <$> view gsimple--isReachable :: TypeGraphVertex key => key -> key -> (Graph, Vertex -> ((), key, [key]), key -> Maybe Vertex) -> Bool-isReachable gkey key0 (g, _vf, kf) = path g (fromJust $ kf key0) (fromJust $ kf gkey)---- | Return the TGV associated with a particular type,--- with no field specified.-typeGraphVertex :: (MonadReader TypeGraph m, DsMonad m) => Type -> m TGV-typeGraphVertex typ = do- typ' <- expandType typ- ask >>= runReaderT (typeVertex' typ') . view typeInfo- -- magnify typeInfo $ vertex Nothing typ'---- | Return the TGV associated with a particular type and field.-typeGraphVertexOfField :: (MonadReader TypeGraph m, DsMonad m) => (Name, Name, Either Int Name) -> Type -> m TGV-typeGraphVertexOfField fld typ = do- typ' <- expandType typ- ask >>= runReaderT (fieldVertex fld typ') . view typeInfo- -- magnify typeInfo $ vertex (Just fld) typ'---- type TypeGraphEdges typ = Map typ (Set typ)---- | When a VertexStatus value is associated with a Type it describes--- alterations in the type graph from the usual default.-data VertexStatus typ- = Vertex -- ^ normal case- | Sink -- ^ out degree zero - don't create any outgoing edges- | Divert typ -- ^ replace all outgoing edges with an edge to an alternate type- | Extra typ -- ^ add an extra outgoing edge to the given type- deriving Show--instance Default (VertexStatus typ) where- def = Vertex----- type Edges = GraphEdges TGV---- | Return the set of edges implied by the subtype relationship among--- a set of types. This is just the nodes of the type graph. The--- type aliases are expanded by the th-desugar package to make them--- suitable for use as map keys.-typeGraphEdges'- :: forall m. (DsMonad m, MonadReader TypeGraph m, HasSet TGV m) =>- (TGV -> m (Set TGV))- -- ^ This function is applied to every expanded type before- -- use, and the result is used instead. If it returns- -- NoVertex, no vertices or edges are added to the graph.- -- If it returns Sink no outgoing edges are added. The- -- current use case Substitute is to see if there is an- -- instance of class @View a b@ where @a@ is the type- -- passed to @doType@, and replace it with @b@, and use the- -- lens returned by @View's@ method to convert between @a@- -- and @b@ (i.e. to implement the edge in the type graph.)- -> [Type]- -> m (GraphEdges TGV)-typeGraphEdges' augment types = do- execStateT (mapM_ (\typ -> typeGraphVertex typ >>= doNode) types) (mempty :: GraphEdges TGV)- where- doNode v = do- s <- lift $ getSet- when (not (member v s)) $- do lift $ modifySet (Set.insert v)- doNode' v- doNode' :: TGV -> StateT (GraphEdges TGV) m ()- doNode' typ = do- addNode typ- vs <- lift $ augment typ- mapM_ (addEdge typ) (Set.toList vs)- mapM_ doNode (Set.toList vs)-- addNode :: TGV -> StateT (GraphEdges TGV) m ()- addNode a = modify $ Map.alter (maybe (Just Set.empty) Just) a-- addEdge :: TGV -> TGV -> StateT (GraphEdges TGV) m ()- addEdge a b = modify $ Map.update (\s -> Just (Set.insert b s)) a---- | Return the set of adjacent vertices according to the default type--- graph - i.e. the one determined only by the type definitions, not--- by any additional hinting function.-adjacent :: forall m. (MonadReader TypeGraph m, DsMonad m) => TGV -> m (Set TGV)-adjacent typ =- case view (vsimple . etype) typ of- E (ForallT _ _ typ') -> typeGraphVertex typ' >>= adjacent- E (AppT c e) ->- typeGraphVertex c >>= \c' ->- typeGraphVertex e >>= \e' ->- return $ Set.fromList [c', e']- E (ConT name) -> do- info <- qReify name- case info of- TyConI dec -> doDec dec- _ -> return mempty- _typ -> return $ {-trace ("Unrecognized type: " ++ pprint' typ)-} mempty- where- doDec :: Dec -> m (Set TGV)- doDec dec@(NewtypeD _ tname _ con _) = doCon tname dec con- doDec dec@(DataD _ tname _ cns _) = Set.unions <$> Traversable.mapM (doCon tname dec) cns- doDec (TySynD _tname _tvars typ') = singleton <$> typeGraphVertex typ'- doDec _ = return mempty-- doCon :: Name -> Dec -> Con -> m (Set TGV)- doCon tname dec (ForallC _ _ con) = doCon tname dec con- doCon tname dec (NormalC cname fields) = Set.unions <$> Traversable.mapM (doField tname dec cname) (zip (List.map Left ([1..] :: [Int])) (List.map snd fields))- doCon tname dec (RecC cname fields) = Set.unions <$> Traversable.mapM (doField tname dec cname) (List.map (\ (fname, _, typ') -> (Right fname, typ')) fields)- doCon tname dec (InfixC (_, lhs) cname (_, rhs)) = Set.unions <$> Traversable.mapM (doField tname dec cname) [(Left 1, lhs), (Left 2, rhs)]-- doField :: Name -> Dec -> Name -> (Either Int Name, Type) -> m (Set TGV)- doField tname _dec cname (fld, ftype) = Set.singleton <$> typeGraphVertexOfField (tname, cname, fld) ftype---- FIXME: pass in ti, pass in makeTypeGraphEdges, remove Q, move to TypeGraph.Graph-makeTypeGraph :: MonadReader TypeInfo m => (GraphEdges TGV) -> m TypeGraph-makeTypeGraph es = do- ti <- ask- return $ TypeGraph- { _typeInfo = ti- , _edges = es- , _graph = graphFromMap es- , _gsimple = graphFromMap (simpleEdges es)- , _stack = []- }
+ Language/Haskell/TH/TypeGraph/HasState.hs view
@@ -0,0 +1,45 @@+-- | MonadState without the function dependency @m -> s@.+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module Language.Haskell.TH.TypeGraph.HasState+ ( HasState(getState, modifyState)+ ) where++import Control.Monad.Reader (ReaderT)+import Control.Monad.RWS (RWST)+import Control.Monad.State (StateT, get, modify)+import Control.Monad.Trans (lift)+import Control.Monad.Writer (WriterT)++-- | This class allows you to access bits of the State by type,+-- without knowing exactly what the overall state type is. For+-- example:+--+-- typeGraphEdges :: (DsMonad m,+-- MonadReader TypeGraph m,+-- HasState (Set TGV) m,+-- HasState (Map Type (E Type)) m) => ...+--+-- This will work as long as the two HasState instances exist for+-- whatever the actual State type is. It still can't reach down+-- into nested StateT monads, you may need to use lift for that.++class HasState s m where+ getState :: m s+ modifyState :: (s -> s) -> m ()++instance Monad m => HasState s (StateT s m) where+ getState = get+ modifyState = modify++instance (Monad m, Monoid w) => HasState s (RWST r w s m) where+ getState = get+ modifyState = modify++instance (Monad m, HasState s m) => HasState s (ReaderT r m) where+ getState = lift getState+ modifyState f = lift $ modifyState f++instance (Monad m, Monoid w, HasState s m) => HasState s (WriterT w m) where+ getState = lift getState+ modifyState f = lift $ modifyState f
− Language/Haskell/TH/TypeGraph/Info.hs
@@ -1,192 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# OPTIONS_GHC -Wall #-}-module Language.Haskell.TH.TypeGraph.Info- ( -- * Type and builders- TypeInfo, startTypes, fields, infoMap, synonyms, typeSet- , makeTypeInfo- -- * Update- , typeVertex- , typeVertex'- , fieldVertex- -- * Query- , fieldVertices- , allVertices- ) where--#if __GLASGOW_HASKELL__ < 709-import Data.Monoid (mempty)-#endif-import Control.Lens -- (makeLenses, view)-import Control.Monad.Reader (MonadReader)-import Control.Monad.State (execStateT, StateT)-import Control.Monad.Trans as Monad (lift)-import Data.Foldable as Foldable (mapM_)-import Data.List as List (intercalate, map)-import Data.Map as Map (findWithDefault, insert, insertWith, Map, toList)-import Data.Set.Extra as Set (empty, insert, map, mapM_, member, Set, singleton, toList, union)-import Language.Haskell.Exts.Syntax ()-import Language.Haskell.TH-import Language.Haskell.TH.Desugar as DS (DsMonad)-import Language.Haskell.TH.Instances ()-import Language.Haskell.TH.PprLib (ptext)-import Language.Haskell.TH.Syntax as TH (Lift(lift), Quasi(..))-import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType)-import Language.Haskell.TH.TypeGraph.Prelude (pprint')-import Language.Haskell.TH.TypeGraph.Shape (Field)-import Language.Haskell.TH.TypeGraph.Vertex (TGV(..), TGVSimple(..), etype)---- | Information collected about the graph implied by the structure of--- one or more 'Type' values.-data TypeInfo- = TypeInfo- { _startTypes :: [Type]- -- ^ The kernel of types from which the others in _typeSet are discovered- , _typeSet :: Set Type- -- ^ All the types encountered, including embedded types such as the- -- 'Maybe' and the 'Int' in @Maybe Int@.- , _infoMap :: Map Name Info- -- ^ The Info record of all known named types- , _expanded :: Map Type (E Type)- -- ^ Map of the expansion of all encountered types- , _synonyms :: Map (E Type) (Set Name)- -- ^ The types with all type synonyms replaced with their expansions.- , _fields :: Map (E Type) (Set (Name, Name, Either Int Name))- -- ^ Map from field type to field names- } deriving (Show, Eq, Ord)--instance Ppr TypeInfo where- ppr (TypeInfo {_typeSet = t, _infoMap = i, _expanded = e, _synonyms = s, _fields = f}) =- ptext $ intercalate "\n " ["TypeInfo:", ppt, ppi, ppe, pps, ppf] ++ "\n"- where- ppt = intercalate "\n " ("typeSet:" : concatMap (lines . pprint) (Set.toList t))- ppi = intercalate "\n " ("infoMap:" : concatMap (lines . (\ (name, info) -> show name ++ " -> " ++ pprint info)) (Map.toList i))- ppe = intercalate "\n " ("expanded:" : concatMap (lines . (\ (typ, (E etyp)) -> pprint typ ++ " -> " ++ pprint etyp)) (Map.toList e))- pps = intercalate "\n " ("synonyms:" : concatMap (lines . (\ (typ, ns) -> pprint typ ++ " -> " ++ show ns)) (Map.toList s))- ppf = intercalate "\n " ("fields:" : concatMap (lines . (\ (typ, fs) -> pprint typ ++ " -> " ++ show fs)) (Map.toList f))--$(makeLenses ''TypeInfo)--instance Lift TypeInfo where- lift (TypeInfo {_startTypes = st, _typeSet = t, _infoMap = i, _expanded = e, _synonyms = s, _fields = f}) =- [| TypeInfo { _startTypes = $(TH.lift st)- , _typeSet = $(TH.lift t)- , _infoMap = $(TH.lift i)- , _expanded = $(TH.lift e)- , _synonyms = $(TH.lift s)- , _fields = $(TH.lift f)- } |]---- | Collect the graph information for one type and all the types--- reachable from it.-collectTypeInfo :: forall m. DsMonad m => (Type -> m (Set Type)) -> Type -> StateT TypeInfo m ()-collectTypeInfo extraTypes typ0 = do- doType typ0- where- doType :: Type -> StateT TypeInfo m ()- doType typ = Monad.lift (extraTypes typ) >>= Set.mapM_ doType' . Set.insert typ-- doType' :: Type -> StateT TypeInfo m ()- doType' typ = do- (s :: Set Type) <- use typeSet- case Set.member typ s of- True -> return ()- False -> do typeSet %= Set.insert typ- etyp{-@(E etyp')-} <- expandType typ- expanded %= Map.insert typ etyp- -- expanded %= Map.insert etyp' etyp -- A type is its own expansion, but we shouldn't need this- doType'' typ-- doType'' :: Type -> StateT TypeInfo m ()- doType'' (ConT name) = do- info <- qReify name- infoMap %= Map.insert name info- doInfo name info- doType'' (AppT typ1 typ2) = doType typ1 >> doType typ2- doType'' ListT = return ()- doType'' (VarT _) = return ()- doType'' (TupleT _) = return ()- doType'' typ = error $ "makeTypeInfo: " ++ pprint' typ-- doInfo :: Name -> Info -> StateT TypeInfo m ()- doInfo _tname (TyConI dec) = doDec dec- doInfo _tname (PrimTyConI _ _ _) = return ()- doInfo _tname (FamilyI _ _) = return () -- Not sure what to do here- doInfo _ info = error $ "makeTypeInfo: " ++ show info-- doDec :: Dec -> StateT TypeInfo m ()- doDec (TySynD tname _ typ) = do- etyp <- expandType (ConT tname)- synonyms %= Map.insertWith union etyp (singleton tname)- doType typ- doDec (NewtypeD _ tname _ constr _) = doCon tname constr- doDec (DataD _ tname _ constrs _) = Foldable.mapM_ (doCon tname) constrs- doDec dec = error $ "makeTypeInfo: " ++ pprint' dec-- doCon :: Name -> Con -> StateT TypeInfo m ()- doCon tname (ForallC _ _ con) = doCon tname con- doCon tname (NormalC cname flds) = Foldable.mapM_ doField (zip (List.map (\n -> (tname, cname, Left n)) ([1..] :: [Int])) (List.map snd flds))- doCon tname (RecC cname flds) = Foldable.mapM_ doField (List.map (\ (fname, _, ftype) -> ((tname, cname, Right fname), ftype)) flds)- doCon tname (InfixC (_, lhs) cname (_, rhs)) = Foldable.mapM_ doField [((tname, cname, Left 1), lhs), ((tname, cname, Left 2), rhs)]-- doField :: ((Name, Name, Either Int Name), Type) -> StateT TypeInfo m ()- doField (fld, ftyp) = do- etyp <- expandType ftyp- fields %= Map.insertWith union etyp (singleton fld)- doType ftyp---- | Build a TypeInfo value by scanning the supplied types-makeTypeInfo :: forall m. DsMonad m => (Type -> m (Set Type)) -> [Type] -> m TypeInfo-makeTypeInfo extraTypes types =- execStateT- (Foldable.mapM_ (collectTypeInfo extraTypes) types)- (TypeInfo { _startTypes = types- , _typeSet = mempty- , _infoMap = mempty- , _expanded = mempty- , _synonyms = mempty- , _fields = mempty})--allVertices :: (Functor m, DsMonad m, MonadReader TypeInfo m) => Maybe Field -> E Type -> m (Set TGV)-allVertices (Just fld) etyp = singleton <$> fieldVertex fld etyp-allVertices Nothing etyp = do- v <- typeVertex etyp- vs <- fieldVertices v- return $ Set.insert (TGV {_vsimple = v, _field = Nothing}) vs---- | Find the vertices that involve a particular type - if the field--- is specified it return s singleton, otherwise it returns a set--- containing a vertex one for the type on its own, and one for each--- field containing that type.-fieldVertices :: MonadReader TypeInfo m => TGVSimple -> m (Set TGV)-fieldVertices v = do- fm <- view fields- let fs = Map.findWithDefault Set.empty (view etype v) fm- return $ Set.map (\fld' -> TGV {_vsimple = v, _field = Just fld'}) fs---- | Build a vertex from the given 'Type' and optional 'Field'.--- vertex :: forall m. (DsMonad m, MonadReader TypeInfo m) => Maybe Field -> E Type -> m TypeGraphVertex--- vertex fld etyp = maybe (typeVertex etyp) (fieldVertex etyp) fld---- | Build a non-field vertex-typeVertex :: MonadReader TypeInfo m => E Type -> m TGVSimple-typeVertex etyp = do- sm <- view synonyms- return $ TGVSimple {_syns = Map.findWithDefault Set.empty etyp sm, _etype = etyp}--typeVertex' :: MonadReader TypeInfo m => E Type -> m TGV-typeVertex' etyp = do- v <- typeVertex etyp- return $ TGV {_vsimple = v, _field = Nothing}---- | Build a vertex associated with a field-fieldVertex :: MonadReader TypeInfo m => Field -> E Type -> m TGV-fieldVertex fld' etyp = typeVertex etyp >>= \v -> return $ TGV {_vsimple = v, _field = Just fld'}
Language/Haskell/TH/TypeGraph/Prelude.hs view
@@ -11,7 +11,6 @@ , constructorName , declarationName , declarationType- , HasSet(getSet, modifySet) , unReify , unReifyName , adjacent'@@ -96,17 +95,11 @@ declarationName (TySynInstD name _) = Just name declarationName (ClosedTypeFamilyD name _ _ _) = Just name declarationName (RoleAnnotD name _) = Just name-#if __GLASGOW_HASKELL__ >= 709 declarationName (StandaloneDerivD _ _) = Nothing declarationName (DefaultSigD name _) = Just name-#endif declarationType :: Dec -> Maybe Type declarationType = fmap ConT . declarationName--class HasSet a m where- getSet :: m (Set a)- modifySet :: (Set a -> Set a) -> m () instance Lift a => Lift (Set a) where lift s = [|Set.fromList $(lift (Set.toList s))|]
Language/Haskell/TH/TypeGraph/Shape.hs view
@@ -1,4 +1,4 @@--- | A fold on the shape of a record.+-- | A fold on the shape of the constructors of a DataD or NewtypeD record. {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-}
Language/Haskell/TH/TypeGraph/Stack.hs view
@@ -43,13 +43,15 @@ import Debug.Trace (trace) import Language.Haskell.Exts.Syntax () import Language.Haskell.TH+import Language.Haskell.TH.Desugar (DsMonad) import Language.Haskell.TH.Instances () import Language.Haskell.TH.Syntax hiding (lift) import Language.Haskell.TH.TypeGraph.Edges (GraphEdges, simpleEdges, typeGraphEdges)-import Language.Haskell.TH.TypeGraph.Expand (E(E))-import Language.Haskell.TH.TypeGraph.Info (makeTypeInfo)+import Language.Haskell.TH.TypeGraph.Expand (E(E), ExpandMap)+import Language.Haskell.TH.TypeGraph.HasState (HasState) import Language.Haskell.TH.TypeGraph.Prelude (constructorName) import Language.Haskell.TH.TypeGraph.Shape (FieldType(..), fName, fType, constructorFieldTypes)+import Language.Haskell.TH.TypeGraph.TypeInfo (makeTypeInfo) import Language.Haskell.TH.TypeGraph.Vertex (etype, TGV) import Prelude hiding ((.)) @@ -181,7 +183,7 @@ -- The only reason for this function is backwards compatibility, the -- fields should be changed so they begin with _ and the regular -- makeLenses should be used.-makeLenses' :: (Type -> Q (Set Type)) -> [Name] -> Q [Dec]+makeLenses' :: forall m. (DsMonad m, HasState ExpandMap m) => (Type -> m (Set Type)) -> [Name] -> m [Dec] makeLenses' extraTypes typeNames = execWriterT $ execStackT $ makeTypeInfo (lift . lift . extraTypes) st >>= runReaderT typeGraphEdges >>= \ (g :: GraphEdges TGV) -> (mapM doType . map (view etype) . Map.keys . simpleEdges $ g) where@@ -195,7 +197,7 @@ doCons dec typeName cons = mapM_ (\ con -> mapM_ (foldField (doField typeName) dec con) (constructorFieldTypes con)) cons -- (mkName $ nameBase $ tName dec) dec lensNamer) >>= tell- doField :: Name -> FieldType -> StackT (WriterT [Dec] Q) ()+ doField :: Name -> FieldType -> StackT (WriterT [Dec] m) () doField typeName (Named (fieldName, _, fieldType)) = doFieldType typeName fieldName fieldType doField _ _ = return ()
+ Language/Haskell/TH/TypeGraph/TypeGraph.hs view
@@ -0,0 +1,264 @@+-- | Abstract operations on Maps containing graph edges.++{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE TypeFamilies #-}++module Language.Haskell.TH.TypeGraph.TypeGraph+ ( TypeGraph, typeInfo, edges, graph, gsimple, stack+ , graphFromMap++ , allLensKeys+ , allPathKeys+ , allPathStarts+ , reachableFrom+ , reachableFromSimple+ , goalReachableFull+ , goalReachableSimple+ , goalReachableSimple'++ , makeTypeGraph+ , VertexStatus(..)+ , typeGraphEdges'+ , adjacent+ , typeGraphVertex+ , typeGraphVertexOfField+ ) where++#if __GLASGOW_HASKELL__ < 709+import Control.Applicative+import Data.Monoid (mempty)+#else+import Control.Applicative+#endif+import Control.Lens -- (makeLenses, over, view)+import Control.Monad (when)+import Control.Monad.Reader (ask, local, MonadReader, ReaderT, runReaderT)+import Control.Monad.State (execStateT, modify, StateT)+import Control.Monad.Trans (lift)+import Data.Default (Default(def))+import Data.Foldable as Foldable+import Data.Graph hiding (edges)+import Data.List as List (map)+import Data.Map as Map (alter, fromList, fromListWith, Map, update)+import qualified Data.Map as Map (toList)+import Data.Maybe (fromJust, mapMaybe)+import Data.Set.Extra as Set (empty, fromList, insert, map, member, Set, singleton, toList, union, unions)+import Data.Traversable as Traversable+import Language.Haskell.Exts.Syntax ()+import Language.Haskell.TH+import Language.Haskell.TH.Desugar (DsMonad)+import Language.Haskell.TH.Instances ()+import Language.Haskell.TH.PprLib (ptext)+import Language.Haskell.TH.Syntax (Quasi(..))+import Language.Haskell.TH.TypeGraph.Edges (GraphEdges, simpleEdges)+import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType)+import Language.Haskell.TH.TypeGraph.HasState (HasState(getState, modifyState))+import Language.Haskell.TH.TypeGraph.Prelude (adjacent', reachable')+import Language.Haskell.TH.TypeGraph.TypeInfo (startTypes, TypeInfo, typeVertex', fieldVertex)+import Language.Haskell.TH.TypeGraph.Stack (HasStack(withStack, push), StackElement(StackElement))+import Language.Haskell.TH.TypeGraph.Vertex (TGV, TGVSimple, vsimple, TypeGraphVertex, etype)+import Prelude hiding (any, concat, concatMap, elem, exp, foldr, mapM_, null, or)++instance Ppr Vertex where+ ppr n = ptext ("V" ++ show n)++-- | Build a graph from the result of typeGraphEdges, each edge goes+-- from a type to one of the types it contains. Thus, each edge+-- represents a primitive lens, and each path in the graph is a+-- composition of lenses.+graphFromMap :: forall key. (Ord key) =>+ GraphEdges key -> (Graph, Vertex -> ((), key, [key]), key -> Maybe Vertex)+graphFromMap mp =+ graphFromEdges triples+ where+ triples :: [((), key, [key])]+ triples = List.map (\ (k, ks) -> ((), k, Foldable.toList ks)) $ Map.toList mp++data TypeGraph+ = TypeGraph+ { _typeInfo :: TypeInfo+ , _edges :: GraphEdges TGV+ , _graph :: (Graph, Vertex -> ((), TGV, [TGV]), TGV -> Maybe Vertex)+ , _gsimple :: (Graph, Vertex -> ((), TGVSimple, [TGVSimple]), TGVSimple -> Maybe Vertex)+ , _stack :: [StackElement]+ }++$(makeLenses ''TypeGraph)++instance Monad m => HasStack (ReaderT TypeGraph m) where+ withStack f = ask >>= f . view stack+ push fld con dec action = local (stack %~ (\s -> StackElement fld con dec : s)) action++allPathStarts :: forall m. (DsMonad m, HasState (Map Type (E Type)) m, MonadReader TypeGraph m) => m (Set TGV)+allPathStarts = do+ -- (g, vf, kf) <- graphFromMap <$> view edges+ (g, vf, kf) <- view graph+ kernel <- view typeInfo >>= \ti -> runReaderT (Traversable.mapM expandType (view startTypes ti) >>= Traversable.mapM typeVertex') ti+ let keep = Set.fromList $ concatMap (reachable g) (mapMaybe kf kernel)+ keep' = Set.map (view _2) . Set.map vf $ keep+ return keep'++-- | Lenses represent steps in a path, but the start point is a type+-- vertex and the endpoint is a field vertex.+allLensKeys :: (DsMonad m, HasState (Map Type (E Type)) m, MonadReader TypeGraph m) => m (Map TGVSimple (Set TGV))+allLensKeys = do+ g <- view graph+ gs <- view gsimple+ allPathStarts >>= return . Map.fromListWith Set.union . List.map (\x -> (view vsimple x, Set.fromList (adjacent' g x))) . Set.toList++-- | Paths go between simple types.+allPathKeys :: (DsMonad m, HasState (Map Type (E Type)) m, MonadReader TypeGraph m) => m (Map TGVSimple (Set TGVSimple))+allPathKeys = do+ gs <- view gsimple+ allPathStarts >>= return . Map.fromList . List.map (\x -> (x, Set.fromList (reachable' gs x))) . Set.toList . Set.map (view vsimple)++reachableFrom :: forall m. (DsMonad m, MonadReader TypeGraph m) => TGV -> m (Set TGV)+reachableFrom v = do+ -- (g, vf, kf) <- graphFromMap <$> view edges+ (g, vf, kf) <- view graph+ case kf v of+ Nothing -> return Set.empty+ Just v' -> return $ Set.map (\(_, key, _) -> key) . Set.map vf $ Set.fromList $ reachable (transposeG g) v'++reachableFromSimple :: forall m. (DsMonad m, MonadReader TypeGraph m) => TGVSimple -> m (Set TGVSimple)+reachableFromSimple v = do+ -- (g, vf, kf) <- graphFromMap <$> view edges+ (g, vf, kf) <- view gsimple+ case kf v of+ Nothing -> return Set.empty+ Just v' -> return $ Set.map (\(_, key, _) -> key) . Set.map vf $ Set.fromList $ reachable (transposeG g) v'++-- | Can we reach the goal type from the start type in this key?+goalReachableFull :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGV -> TGV -> m Bool+goalReachableFull gkey key0 = isReachable gkey key0 <$> view graph++goalReachableSimple :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGVSimple -> TGVSimple -> m Bool+goalReachableSimple gkey key0 = isReachable gkey key0 <$> view gsimple++goalReachableSimple' :: (Functor m, DsMonad m, MonadReader TypeGraph m) => TGV -> TGV -> m Bool+goalReachableSimple' gkey key0 = isReachable (view vsimple gkey) (view vsimple key0) <$> view gsimple++isReachable :: TypeGraphVertex key => key -> key -> (Graph, Vertex -> ((), key, [key]), key -> Maybe Vertex) -> Bool+isReachable gkey key0 (g, _vf, kf) = path g (fromJust $ kf key0) (fromJust $ kf gkey)++-- | Return the TGV associated with a particular type,+-- with no field specified.+typeGraphVertex :: (MonadReader TypeGraph m, HasState (Map Type (E Type)) m, DsMonad m) => Type -> m TGV+typeGraphVertex typ = do+ typ' <- expandType typ+ ask >>= runReaderT (typeVertex' typ') . view typeInfo+ -- magnify typeInfo $ vertex Nothing typ'++-- | Return the TGV associated with a particular type and field.+typeGraphVertexOfField :: (MonadReader TypeGraph m, HasState (Map Type (E Type)) m, DsMonad m) => (Name, Name, Either Int Name) -> Type -> m TGV+typeGraphVertexOfField fld typ = do+ typ' <- expandType typ+ ask >>= runReaderT (fieldVertex fld typ') . view typeInfo+ -- magnify typeInfo $ vertex (Just fld) typ'++-- type TypeGraphEdges typ = Map typ (Set typ)++-- | When a VertexStatus value is associated with a Type it describes+-- alterations in the type graph from the usual default.+data VertexStatus typ+ = Vertex -- ^ normal case+ | Sink -- ^ out degree zero - don't create any outgoing edges+ | Divert typ -- ^ replace all outgoing edges with an edge to an alternate type+ | Extra typ -- ^ add an extra outgoing edge to the given type+ deriving Show++instance Default (VertexStatus typ) where+ def = Vertex++--- type Edges = GraphEdges TGV++-- | Return the set of edges implied by the subtype relationship among+-- a set of types. This is just the nodes of the type graph. The+-- type aliases are expanded by the th-desugar package to make them+-- suitable for use as map keys.+typeGraphEdges'+ :: forall m. (DsMonad m, MonadReader TypeGraph m, HasState (Set TGV) m, HasState (Map Type (E Type)) m) =>+ (TGV -> m (Set TGV))+ -- ^ This function is applied to every expanded type before+ -- use, and the result is used instead. If it returns+ -- NoVertex, no vertices or edges are added to the graph.+ -- If it returns Sink no outgoing edges are added. The+ -- current use case Substitute is to see if there is an+ -- instance of class @View a b@ where @a@ is the type+ -- passed to @doType@, and replace it with @b@, and use the+ -- lens returned by @View's@ method to convert between @a@+ -- and @b@ (i.e. to implement the edge in the type graph.)+ -> [Type]+ -> m (GraphEdges TGV)+typeGraphEdges' augment types = do+ execStateT (mapM_ (\typ -> lift (typeGraphVertex typ) >>= doNode) types) (mempty :: GraphEdges TGV)+ where+ doNode v = do+ (s :: Set TGV) <- lift $ getState+ when (not (member v s)) $+ do lift $ modifyState (Set.insert v)+ doNode' v+ doNode' :: TGV -> StateT (GraphEdges TGV) m ()+ doNode' typ = do+ addNode typ+ vs <- lift $ augment typ+ mapM_ (addEdge typ) (Set.toList vs)+ mapM_ doNode (Set.toList vs)++ addNode :: TGV -> StateT (GraphEdges TGV) m ()+ addNode a = modify $ Map.alter (maybe (Just Set.empty) Just) a++ addEdge :: TGV -> TGV -> StateT (GraphEdges TGV) m ()+ addEdge a b = modify $ Map.update (\s -> Just (Set.insert b s)) a++-- | Return the set of adjacent vertices according to the default type+-- graph - i.e. the one determined only by the type definitions, not+-- by any additional hinting function.+adjacent :: forall m. (MonadReader TypeGraph m, DsMonad m, HasState (Map Type (E Type)) m) => TGV -> m (Set TGV)+adjacent typ =+ case view (vsimple . etype) typ of+ E (ForallT _ _ typ') -> typeGraphVertex typ' >>= adjacent+ E (AppT c e) ->+ typeGraphVertex c >>= \c' ->+ typeGraphVertex e >>= \e' ->+ return $ Set.fromList [c', e']+ E (ConT name) -> do+ info <- qReify name+ case info of+ TyConI dec -> doDec dec+ _ -> return mempty+ _typ -> return $ {-trace ("Unrecognized type: " ++ pprint' typ)-} mempty+ where+ doDec :: Dec -> m (Set TGV)+ doDec dec@(NewtypeD _ tname _ con _) = doCon tname dec con+ doDec dec@(DataD _ tname _ cns _) = Set.unions <$> Traversable.mapM (doCon tname dec) cns+ doDec (TySynD _tname _tvars typ') = singleton <$> typeGraphVertex typ'+ doDec _ = return mempty++ doCon :: Name -> Dec -> Con -> m (Set TGV)+ doCon tname dec (ForallC _ _ con) = doCon tname dec con+ doCon tname dec (NormalC cname fields) = Set.unions <$> Traversable.mapM (doField tname dec cname) (zip (List.map Left ([1..] :: [Int])) (List.map snd fields))+ doCon tname dec (RecC cname fields) = Set.unions <$> Traversable.mapM (doField tname dec cname) (List.map (\ (fname, _, typ') -> (Right fname, typ')) fields)+ doCon tname dec (InfixC (_, lhs) cname (_, rhs)) = Set.unions <$> Traversable.mapM (doField tname dec cname) [(Left 1, lhs), (Left 2, rhs)]++ doField :: Name -> Dec -> Name -> (Either Int Name, Type) -> m (Set TGV)+ doField tname _dec cname (fld, ftype) = Set.singleton <$> typeGraphVertexOfField (tname, cname, fld) ftype++-- FIXME: pass in ti, pass in makeTypeGraphEdges, remove Q, move to TypeGraph.Graph+makeTypeGraph :: MonadReader TypeInfo m => (GraphEdges TGV) -> m TypeGraph+makeTypeGraph es = do+ ti <- ask+ return $ TypeGraph+ { _typeInfo = ti+ , _edges = es+ , _graph = graphFromMap es+ , _gsimple = graphFromMap (simpleEdges es)+ , _stack = []+ }
+ Language/Haskell/TH/TypeGraph/TypeInfo.hs view
@@ -0,0 +1,199 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# OPTIONS_GHC -Wall #-}+module Language.Haskell.TH.TypeGraph.TypeInfo+ ( -- * Type and builders+ TypeInfo, startTypes, fields, infoMap, synonyms, typeSet+ , makeTypeInfo+ -- * Update+ , typeVertex+ , typeVertex'+ , fieldVertex+ -- * Query+ , fieldVertices+ , allVertices+ ) where++#if __GLASGOW_HASKELL__ < 709+import Data.Monoid (mempty)+#endif+import Control.Lens -- (makeLenses, view)+import Control.Monad.Reader (MonadReader)+import Control.Monad.State (execStateT, StateT)+import Control.Monad.Trans as Monad (lift)+import Data.Foldable as Foldable (mapM_)+import Data.List as List (intercalate, map)+import Data.Map as Map (findWithDefault, insert, insertWith, Map, toList)+import Data.Set.Extra as Set (empty, insert, map, mapM_, member, Set, singleton, toList, union)+import Language.Haskell.Exts.Syntax ()+import Language.Haskell.TH+import Language.Haskell.TH.Desugar as DS (DsMonad)+import Language.Haskell.TH.Instances ()+import Language.Haskell.TH.PprLib (ptext)+import Language.Haskell.TH.Syntax as TH (Lift(lift), Quasi(..))+import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType)+import Language.Haskell.TH.TypeGraph.HasState (HasState(getState, modifyState))+import Language.Haskell.TH.TypeGraph.Prelude (pprint')+import Language.Haskell.TH.TypeGraph.Shape (Field)+import Language.Haskell.TH.TypeGraph.Vertex (TGV(..), TGVSimple(..), etype)++-- | Information collected about the graph implied by the structure of+-- one or more 'Type' values.+data TypeInfo+ = TypeInfo+ { _startTypes :: [Type]+ -- ^ The kernel of types from which the others in _typeSet are discovered+ , _typeSet :: Set Type+ -- ^ All the types encountered, including embedded types such as the+ -- 'Maybe' and the 'Int' in @Maybe Int@.+ , _infoMap :: Map Name Info+ -- ^ The Info record of all known named types+ , _expanded :: Map Type (E Type)+ -- ^ Map of the expansion of all encountered types+ , _synonyms :: Map (E Type) (Set Name)+ -- ^ The types with all type synonyms replaced with their expansions.+ , _fields :: Map (E Type) (Set (Name, Name, Either Int Name))+ -- ^ Map from field type to field names+ } deriving (Show, Eq, Ord)++instance Ppr TypeInfo where+ ppr (TypeInfo {_typeSet = t, _infoMap = i, _expanded = e, _synonyms = s, _fields = f}) =+ ptext $ intercalate "\n " ["TypeInfo:", ppt, ppi, ppe, pps, ppf] ++ "\n"+ where+ ppt = intercalate "\n " ("typeSet:" : concatMap (lines . pprint) (Set.toList t))+ ppi = intercalate "\n " ("infoMap:" : concatMap (lines . (\ (name, info) -> show name ++ " -> " ++ pprint info)) (Map.toList i))+ ppe = intercalate "\n " ("expanded:" : concatMap (lines . (\ (typ, (E etyp)) -> pprint typ ++ " -> " ++ pprint etyp)) (Map.toList e))+ pps = intercalate "\n " ("synonyms:" : concatMap (lines . (\ (typ, ns) -> pprint typ ++ " -> " ++ show ns)) (Map.toList s))+ ppf = intercalate "\n " ("fields:" : concatMap (lines . (\ (typ, fs) -> pprint typ ++ " -> " ++ show fs)) (Map.toList f))++$(makeLenses ''TypeInfo)++instance Monad m => HasState (Map Type (E Type)) (StateT TypeInfo m) where+ getState = use expanded+ modifyState f = expanded %= f++instance Lift TypeInfo where+ lift (TypeInfo {_startTypes = st, _typeSet = t, _infoMap = i, _expanded = e, _synonyms = s, _fields = f}) =+ [| TypeInfo { _startTypes = $(TH.lift st)+ , _typeSet = $(TH.lift t)+ , _infoMap = $(TH.lift i)+ , _expanded = $(TH.lift e)+ , _synonyms = $(TH.lift s)+ , _fields = $(TH.lift f)+ } |]++-- | Collect the graph information for one type and all the types+-- reachable from it. The extraTypes function parameter allows extra+-- edges to be added to the graph other than those implied by the Type+-- structure.+collectTypeInfo :: forall m. DsMonad m => (Type -> m (Set Type)) -> Type -> StateT TypeInfo m ()+collectTypeInfo extraTypes typ0 = do+ doType typ0+ where+ doType :: Type -> StateT TypeInfo m ()+ doType typ = Monad.lift (extraTypes typ) >>= Set.mapM_ doType' . Set.insert typ++ doType' :: Type -> StateT TypeInfo m ()+ doType' typ = do+ (s :: Set Type) <- use typeSet+ case Set.member typ s of+ True -> return ()+ False -> do typeSet %= Set.insert typ+ etyp{-@(E etyp')-} <- expandType typ+ expanded %= Map.insert typ etyp+ -- expanded %= Map.insert etyp' etyp -- A type is its own expansion, but we shouldn't need this+ doType'' typ++ doType'' :: Type -> StateT TypeInfo m ()+ doType'' (ConT name) = do+ info <- qReify name+ infoMap %= Map.insert name info+ doInfo name info+ doType'' (AppT typ1 typ2) = doType typ1 >> doType typ2+ doType'' ListT = return ()+ doType'' (VarT _) = return ()+ doType'' (TupleT _) = return ()+ doType'' typ = error $ "makeTypeInfo: " ++ pprint' typ++ doInfo :: Name -> Info -> StateT TypeInfo m ()+ doInfo _tname (TyConI dec) = doDec dec+ doInfo _tname (PrimTyConI _ _ _) = return ()+ doInfo _tname (FamilyI _ _) = return () -- Not sure what to do here+ doInfo _ info = error $ "makeTypeInfo: " ++ show info++ doDec :: Dec -> StateT TypeInfo m ()+ doDec (TySynD tname _ typ) = do+ etyp <- expandType (ConT tname)+ synonyms %= Map.insertWith union etyp (singleton tname)+ doType typ+ doDec (NewtypeD _ tname _ constr _) = doCon tname constr+ doDec (DataD _ tname _ constrs _) = Foldable.mapM_ (doCon tname) constrs+ doDec dec = error $ "makeTypeInfo: " ++ pprint' dec++ doCon :: Name -> Con -> StateT TypeInfo m ()+ doCon tname (ForallC _ _ con) = doCon tname con+ doCon tname (NormalC cname flds) = Foldable.mapM_ doField (zip (List.map (\n -> (tname, cname, Left n)) ([1..] :: [Int])) (List.map snd flds))+ doCon tname (RecC cname flds) = Foldable.mapM_ doField (List.map (\ (fname, _, ftype) -> ((tname, cname, Right fname), ftype)) flds)+ doCon tname (InfixC (_, lhs) cname (_, rhs)) = Foldable.mapM_ doField [((tname, cname, Left 1), lhs), ((tname, cname, Left 2), rhs)]++ doField :: ((Name, Name, Either Int Name), Type) -> StateT TypeInfo m ()+ doField (fld, ftyp) = do+ etyp <- expandType ftyp+ fields %= Map.insertWith union etyp (singleton fld)+ doType ftyp++-- | Build a TypeInfo value by scanning the supplied types+makeTypeInfo :: forall m. DsMonad m => (Type -> m (Set Type)) -> [Type] -> m TypeInfo+makeTypeInfo extraTypes types =+ execStateT+ (Foldable.mapM_ (collectTypeInfo extraTypes) types)+ (TypeInfo { _startTypes = types+ , _typeSet = mempty+ , _infoMap = mempty+ , _expanded = mempty+ , _synonyms = mempty+ , _fields = mempty})++allVertices :: (Functor m, DsMonad m, MonadReader TypeInfo m) => Maybe Field -> E Type -> m (Set TGV)+allVertices (Just fld) etyp = singleton <$> fieldVertex fld etyp+allVertices Nothing etyp = do+ v <- typeVertex etyp+ vs <- fieldVertices v+ return $ Set.insert (TGV {_vsimple = v, _field = Nothing}) vs++-- | Find the vertices that involve a particular type - if the field+-- is specified it return s singleton, otherwise it returns a set+-- containing a vertex one for the type on its own, and one for each+-- field containing that type.+fieldVertices :: MonadReader TypeInfo m => TGVSimple -> m (Set TGV)+fieldVertices v = do+ fm <- view fields+ let fs = Map.findWithDefault Set.empty (view etype v) fm+ return $ Set.map (\fld' -> TGV {_vsimple = v, _field = Just fld'}) fs++-- | Build a vertex from the given 'Type' and optional 'Field'.+-- vertex :: forall m. (DsMonad m, MonadReader TypeInfo m) => Maybe Field -> E Type -> m TypeGraphVertex+-- vertex fld etyp = maybe (typeVertex etyp) (fieldVertex etyp) fld++-- | Build a non-field vertex+typeVertex :: MonadReader TypeInfo m => E Type -> m TGVSimple+typeVertex etyp = do+ sm <- view synonyms+ return $ TGVSimple {_syns = Map.findWithDefault Set.empty etyp sm, _etype = etyp}++typeVertex' :: MonadReader TypeInfo m => E Type -> m TGV+typeVertex' etyp = do+ v <- typeVertex etyp+ return $ TGV {_vsimple = v, _field = Nothing}++-- | Build a vertex associated with a field+fieldVertex :: MonadReader TypeInfo m => Field -> E Type -> m TGV+fieldVertex fld' etyp = typeVertex etyp >>= \v -> return $ TGV {_vsimple = v, _field = Just fld'}
− Language/Haskell/TH/TypeGraph/Unsafe.hs
@@ -1,24 +0,0 @@--- | Degenerate instances of Expanded that must be explicitly imported--- if you want to use them. They are fine for simple uses of--- expandType, but not if you are trying to use the return value of--- expandType as a Map key.--{-# LANGUAGE CPP #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Language.Haskell.TH.TypeGraph.Unsafe () where--import Language.Haskell.TH.TypeGraph.Expand (Expanded(markExpanded, runExpanded'))-import Language.Haskell.TH (Type)--#if __GLASGOW_HASKELL__ < 709-import Language.Haskell.TH (Pred)--instance Expanded Pred Pred where- markExpanded = id- runExpanded' = id-#endif--instance Expanded Type Type where- markExpanded = id- runExpanded' = id
Language/Haskell/TH/TypeGraph/Vertex.hs view
@@ -15,7 +15,7 @@ import Language.Haskell.TH.Instances () import Language.Haskell.TH.PprLib (hcat, ptext) import Language.Haskell.TH.Syntax (Lift(lift))-import Language.Haskell.TH.TypeGraph.Expand (E(E), runExpanded)+import Language.Haskell.TH.TypeGraph.Expand (E(E, unE)) import Language.Haskell.TH.TypeGraph.Prelude (unReify, unReifyName) import Language.Haskell.TH.TypeGraph.Shape (Field) @@ -40,7 +40,7 @@ instance Ppr TGVSimple where ppr (TGVSimple {_syns = ns, _etype = typ}) =- hcat (ppr (unReify (runExpanded typ)) :+ hcat (ppr (unReify (unE typ)) : case (Set.toList ns) of [] -> [] _ -> [ptext " ("] ++@@ -50,7 +50,7 @@ instance Ppr TGV where ppr (TGV {_field = fld, _vsimple = TGVSimple {_syns = ns, _etype = typ}}) =- hcat (ppr (unReify (runExpanded typ)) :+ hcat (ppr (unReify (unE typ)) : case (fld, Set.toList ns) of (Nothing, []) -> [] _ -> [ptext " ("] ++
test/Common.hs view
@@ -13,11 +13,12 @@ import Language.Haskell.TH import Language.Haskell.TH.Desugar (DsMonad) import Language.Haskell.TH.TypeGraph.Edges (GraphEdges)-import Language.Haskell.TH.TypeGraph.Expand (E, markExpanded, runExpanded)-import Language.Haskell.TH.TypeGraph.Info (TypeInfo)+import Language.Haskell.TH.TypeGraph.Expand (E(unE)) import Language.Haskell.TH.TypeGraph.Edges (typeGraphEdges)+import Language.Haskell.TH.TypeGraph.HasState (HasState) import Language.Haskell.TH.TypeGraph.Prelude (pprint') import Language.Haskell.TH.TypeGraph.Shape (Field)+import Language.Haskell.TH.TypeGraph.TypeInfo (TypeInfo) import Language.Haskell.TH.TypeGraph.Vertex (etype, syns, TGV, TGVSimple, TypeGraphVertex, vsimple) import Language.Haskell.TH.Syntax (Lift(lift))@@ -44,23 +45,23 @@ pprintDec = pprint' . unReify pprintType :: E Type -> String-pprintType = pprint' . unReify . runExpanded+pprintType = pprint' . unReify . unE pprintVertex :: Ppr v => v -> String pprintVertex = pprint' pprintPred :: E Pred -> String-pprintPred = pprint' . unReify . runExpanded+pprintPred = pprint' . unReify . unE edgesToStrings :: (TypeGraphVertex v, Ppr v) => GraphEdges v -> [(String, [String])] edgesToStrings mp = List.map (\ (t, s) -> (pprintVertex t, map pprintVertex (Set.toList s))) (Map.toList mp) -typeGraphEdges' :: forall m. (DsMonad m, MonadReader TypeInfo m) => m (GraphEdges TGV)+typeGraphEdges' :: forall m. (DsMonad m, MonadReader TypeInfo m, HasState (Map Type (E Type)) m) => m (GraphEdges TGV) typeGraphEdges' = typeGraphEdges -- | Return a mapping from vertex to all the known type synonyms for -- the type in that vertex.-typeSynonymMap :: forall m. (DsMonad m, MonadReader TypeInfo m) =>+typeSynonymMap :: forall m. (DsMonad m, MonadReader TypeInfo m, HasState (Map Type (E Type)) m) => m (Map TGV (Set Name)) typeSynonymMap = (Map.filter (not . Set.null) .@@ -69,7 +70,7 @@ Map.keys) <$> (typeGraphEdges :: m (GraphEdges TGV)) -- | Like 'typeSynonymMap', but with all field information removed.-typeSynonymMapSimple :: forall m. (DsMonad m, MonadReader TypeInfo m) =>+typeSynonymMapSimple :: forall m. (DsMonad m, MonadReader TypeInfo m, HasState (Map Type (E Type)) m) => m (Map (E Type) (Set Name)) typeSynonymMapSimple = simplify <$> typeSynonymMap
test/TypeGraph.hs view
@@ -9,14 +9,16 @@ #endif import Control.Lens import Control.Monad.Reader (runReaderT)+import Control.Monad.State (evalStateT) import Data.List as List (map)-import Data.Map as Map (Map, fromList, keys)+import Data.Map as Map (Map, empty, fromList, keys) import Data.Set as Set (fromList, singleton) import Language.Haskell.TH+import Language.Haskell.TH.TypeGraph.Arity (typeArity) import Language.Haskell.TH.TypeGraph.Edges (dissolveM, simpleEdges)-import Language.Haskell.TH.TypeGraph.Expand (expandType, runExpanded, E(E))-import Language.Haskell.TH.TypeGraph.Free (freeTypeVars, typeArity)-import Language.Haskell.TH.TypeGraph.Info (makeTypeInfo, synonyms, typeVertex')+import Language.Haskell.TH.TypeGraph.Expand (expandType, E(E, unE))+import Language.Haskell.TH.TypeGraph.Free (freeTypeVars)+import Language.Haskell.TH.TypeGraph.TypeInfo (makeTypeInfo, synonyms, typeVertex') import Language.Haskell.TH.TypeGraph.Vertex (TGV(..), TGVSimple(..), etype) import Language.Haskell.TH.Desugar (withLocalDeclarations) import Language.Haskell.TH.Instances ()@@ -34,37 +36,41 @@ $([t|String|] >>= \string -> makeTypeInfo (const $ return mempty) [string] >>= lift . view synonyms) `shouldBe` (Map.fromList [(E (AppT ListT (ConT ''Char)), Set.singleton ''String)]) it "records a type synonym 2" $ do- $([t|String|] >>= \string -> makeTypeInfo (const $ return mempty) [string] >>= runReaderT (expandType string >>= typeVertex') >>= lift) `shouldBe` (TGV {_field = Nothing, _vsimple = TGVSimple {_syns = singleton ''String, _etype = E (AppT ListT (ConT ''Char))}})+ $([t|String|] >>= \string ->+ flip evalStateT (Map.empty :: Map Type (E Type))+ (makeTypeInfo (const $ return mempty) [string] >>=+ runReaderT (expandType string >>= typeVertex')) >>= lift)+ `shouldBe` (TGV {_field = Nothing, _vsimple = TGVSimple {_syns = singleton ''String, _etype = E (AppT ListT (ConT ''Char))}}) it "can build the TypeInfoGraph for Type" $ do $(runQ [t|Type|] >>= \typ -> makeTypeInfo (const $ return mempty) [typ] >>= lift . pprint) `shouldBe` typeInfoOfType it "can find the edges of the (simplified) subtype graph of Type (typeEdges)" $ do- setDifferences (Set.fromList $(withLocalDeclarations [] $- runQ [t|Type|] >>= \typ ->- makeTypeInfo (const $ return mempty) [typ] >>= runReaderT typeGraphEdges' >>= return . simpleEdges >>=- runQ . lift . edgesToStrings)) simpleTypeEdges+ setDifferences (Set.fromList $(withLocalDeclarations [] $ flip evalStateT (Map.empty :: Map Type (E Type)) $+ runQ [t|Type|] >>= \typ ->+ makeTypeInfo (const $ return mempty) [typ] >>= runReaderT typeGraphEdges' >>= return . simpleEdges >>=+ runQ . lift . edgesToStrings)) simpleTypeEdges `shouldBe` noDifferences it "can find the edges of the (unsimplified) subtype graph of Type (typeEdges)" $ do- setDifferences (Set.fromList $(withLocalDeclarations [] $+ setDifferences (Set.fromList $(withLocalDeclarations [] $ flip evalStateT (Map.empty :: Map Type (E Type)) $ runQ [t|Type|] >>= \typ -> makeTypeInfo (const $ return mempty) [typ] >>= runReaderT typeGraphEdges' >>= runQ . lift . edgesToStrings)) typeEdges `shouldBe` noDifferences it "can find the subtypesOfType" $ do- setDifferences (Set.fromList $(withLocalDeclarations [] $+ setDifferences (Set.fromList $(withLocalDeclarations [] $ flip evalStateT (Map.empty :: Map Type (E Type)) $ runQ [t|Type|] >>= \typ -> makeTypeInfo (const $ return mempty) [typ] >>= runReaderT typeGraphEdges' >>= runQ . lift . List.map pprintVertex . Map.keys)) subtypesOfType `shouldBe` noDifferences it "can find the edges of the arity 0 subtype graph of Type (arity0TypeEdges)" $ do- setDifferences (Set.fromList $(withLocalDeclarations [] $+ setDifferences (Set.fromList $(withLocalDeclarations [] $ flip evalStateT (Map.empty :: Map Type (E Type)) $ runQ [t|Type|] >>= \typ -> makeTypeInfo (const $ return mempty) [typ] >>= runReaderT typeGraphEdges' >>= return . simpleEdges >>=- dissolveM (\ v -> (/= 0) <$> (typeArity . runExpanded . view etype) v) >>=+ dissolveM (\ v -> (/= 0) <$> (typeArity . unE . view etype) v) >>= runQ . lift . edgesToStrings)) arity0TypeEdges `shouldBe` noDifferences #if 0
test/Values.hs view
@@ -8,9 +8,9 @@ import Data.Set as Set (Set, empty, fromList, toList, union) import GHC.Prim -- ByteArray#, Char#, etc import Language.Haskell.TH+import Language.Haskell.TH.TypeGraph.Arity (typeArity) import Language.Haskell.TH.TypeGraph.Edges (typeGraphEdges)-import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType, markExpanded)-import Language.Haskell.TH.TypeGraph.Free (typeArity)+import Language.Haskell.TH.TypeGraph.Expand (E(E), expandType) import Language.Haskell.TH.TypeGraph.Vertex (TypeGraphVertex(..)) import Language.Haskell.TH.Desugar (withLocalDeclarations) import Language.Haskell.TH.Instances ()
th-typegraph.cabal view
@@ -1,5 +1,5 @@ name: th-typegraph-version: 0.23+version: 0.24 cabal-version: >= 1.10 build-type: Simple license: BSD3@@ -24,24 +24,25 @@ data-default, haskell-src-exts, lens,- memoize, mtl, set-extra, syb, template-haskell >= 2.10, th-desugar, th-orphans >= 0.10.0- ghc-options: -Wall- exposed-modules: Language.Haskell.TH.TypeGraph.Edges- Language.Haskell.TH.TypeGraph.Expand- Language.Haskell.TH.TypeGraph.Free- Language.Haskell.TH.TypeGraph.Graph- Language.Haskell.TH.TypeGraph.Info- Language.Haskell.TH.TypeGraph.Prelude- Language.Haskell.TH.TypeGraph.Shape- Language.Haskell.TH.TypeGraph.Stack- Language.Haskell.TH.TypeGraph.Unsafe- Language.Haskell.TH.TypeGraph.Vertex+ ghc-options: -Wall -O2+ exposed-modules:+ Language.Haskell.TH.TypeGraph.Arity+ Language.Haskell.TH.TypeGraph.Edges+ Language.Haskell.TH.TypeGraph.Expand+ Language.Haskell.TH.TypeGraph.Free+ Language.Haskell.TH.TypeGraph.HasState+ Language.Haskell.TH.TypeGraph.Prelude+ Language.Haskell.TH.TypeGraph.Shape+ Language.Haskell.TH.TypeGraph.Stack+ Language.Haskell.TH.TypeGraph.TypeGraph+ Language.Haskell.TH.TypeGraph.TypeInfo+ Language.Haskell.TH.TypeGraph.Vertex default-language: Haskell2010 test-suite th-typegraph-tests