{-# LANGUAGE GADTs, KindSignatures, ExistentialQuantification, Rank2Types #-} {-# OPTIONS_GHC -Wall #-} ---------------------------------------------------------------------- -- | -- Module : Shady.Language.Graph -- Copyright : (c) Conal Elliott 2009 -- License : AGPLv3 -- -- Maintainer : conal@conal.net -- Stability : experimental -- -- Based on a typed variant of Andy Gill's data-reify. After several -- tries, I wasn't able to reuse data-reify or my typed variant of it. -- The problem was that I need my 'HasType' class and 'Type' type, but I -- couldn't parameterize data-reify by the /class/ 'HasType'. ---------------------------------------------------------------------- module Shady.Language.Graph ( -- * Typed identifiers NodeId, Tid(..) -- * Graph nodes , N(..), mapDeRef -- * Bindings , Bind(..) -- * Graphs , Graph(..) ) where import Control.Applicative (Applicative(..),liftA2) import Shady.Language.Operator import Shady.Language.Exp {-------------------------------------------------------------------- Typed identifiers --------------------------------------------------------------------} -- | Node Identifiers type NodeId = Int -- | Typed variables data Tid a = Tid NodeId (Type a) instance Eq (Tid a) where Tid i _ == Tid j _ = i == j instance Show (Tid a) where show (Tid i _) = 'x' : show i {-------------------------------------------------------------------- Graph nodes --------------------------------------------------------------------} data N :: * -> * where VN :: V a -> N a ON :: Op a -> N a App :: (HasType a, HasType b) => Tid (a -> b) -> Tid a -> N b instance Show (N a) where show (VN v) = unwords ["VN" ,show v] show (ON o) = unwords ["ON" ,show o] show (App a b) = unwords ["App",show a,show b] mapDeRef :: Applicative m => (forall a. HasType a => E a -> m NodeId) -> (forall a. HasType a => E a -> m (N a)) mapDeRef _ (Var v) = pure $ VN v mapDeRef _ (Op o) = pure $ ON o mapDeRef f (u :^ v) = liftA2 App (app f u) (app f v) -- liftA2 App (f u) (f v) mapDeRef _ Lam{} = notSupp "Lam" notSupp :: String -> a notSupp meth = error $ "mapDeRef on E: "++meth++" not supported" app :: (Functor m, HasType a) => (E a -> m NodeId) -> E a -> m (Tid a) app f u = fmap (flip Tid (typeOf1 u)) (f u) {-------------------------------------------------------------------- Bindings --------------------------------------------------------------------} -- | Binding pair data Bind = forall a. HasType a => Bind NodeId (N a) instance Show Bind where show (Bind v n) = show v ++" = "++ show n {-------------------------------------------------------------------- Graphs --------------------------------------------------------------------} -- | Graph, described by bindings and a root variable data Graph a = Graph [Bind] (Tid a) instance Show (Graph a) where show (Graph netlist start) = "let " ++ show netlist ++ " in " ++ show start