packages feed

unbound-0.2: examples/functor2.hs

{-# LANGUAGE TemplateHaskell, 
             ScopedTypeVariables,
             FlexibleInstances,
             MultiParamTypeClasses,
             FlexibleContexts,
             UndecidableInstances, 
             GADTs #-}

module Functor2 where

import Generics.RepLib hiding (Int)
import Generics.RepLib.Bind.LocallyNameless
import Control.Monad
import Control.Monad.Trans.Error
import Data.List as List

{- This is the right way to formalize modules and functors
 -}

type TyName = Name Type
type ModName = Name Module 

data Type = TyVar TyName
          | Int
          | Bool
          | Path Module String
   deriving Show

data ModDef =  TyDef  TyName  (Maybe (Annot Type))
            |  ModDef ModName (Annot Module) 

   deriving Show
data Module =  Struct  (Bind (Rec [(String,ModDef)]) ())
            |  Functor (Bind TyName Module)
            |  ModApp Module Type
            |  ModVar (Name Module)
   deriving Show

$(derive [''Type, ''ModDef, ''Module])

------------------------------------------------------  
instance Alpha Type where   
instance Alpha Module where
instance Alpha ModDef where

instance Subst Module Type where

instance Subst Module ModDef
instance Subst Module Module where
  isvar (ModVar x) = Just (SubstName x)
  isvar _ = Nothing

instance Subst Type Module where
instance Subst Type ModDef where
instance Subst Type Type where
  isvar (TyVar x) = Just (SubstName x)
  isvar _ = Nothing


t :: TyName
t = string2Name "t"

u :: TyName
u = string2Name "u"

x :: TyName
x = string2Name "x"

g :: ModName
g = string2Name "G"

f :: Module
f = Functor (bind x  
             (Struct (bind (rec 
                  [("t", TyDef t (Just (Annot Bool))),
                   ("u", TyDef u (Just (Annot (TyVar x))))]) ())))

m :: Module
m = Struct (bind (rec [("t", TyDef t (Just (Annot Int))), 
                       ("g", ModDef g (Annot (ModApp f (TyVar t))))]) ())


red :: Fresh m => Module -> m Module 
red (ModApp m1 t) = do 
  m1' <- red m1
  case m1' of 
    Functor bnd -> do 
       (x, m1'') <- unbind bnd
       red (subst x t m1'')
    _ -> return (ModApp m1 t)
red (Struct s) = do 
    (r,()) <- unbind s
    defs <- mapM redDef (unrec r)
    return (Struct (bind (rec defs) ()))  
red m = return m

redDef :: Fresh m => (String,ModDef) -> m (String,ModDef)
redDef (s,ModDef f (Annot m)) = do 
  m' <- red m
  return (s,ModDef f (Annot m'))
redDef d = return d

m2 :: Module
m2 = runFreshM (red m)