{-# OPTIONS_GHC -fglasgow-exts #-}
module PSTLC where
import Iso
import PGames
import PBasicGames
import Data.Maybe
import FilterGames
-- Simple types
-- /TyExp/
data Ty = TyNat | TyArr Ty Ty deriving (Eq, Show)
data Exp = Var Nat | Lam Ty Exp | App Exp Exp
-- /End/
deriving (Eq,Show)
-- Game for types
-- /tyG/
tyGame :: Game Ty
tyGame = Split (Iso ask bld)
(constGame TyNat) (prodGame tyGame tyGame)
where ask TyNat = Left TyNat
ask (TyArr t1 t2) = Right (t1,t2)
bld (Left TyNat) = TyNat
bld (Right (t1,t2)) = TyArr t1 t2
-- /End/
-- Environment is just a list of types
-- Precondition: expression well typed in environment
-- /typeOf/
type Env = [Ty]
typeOf :: Env -> Exp -> Ty
typeOf env (Var i) = env !! i
typeOf env (App e _) = let TyArr _ t = typeOf env e in t
typeOf env (Lam t e) = TyArr t (typeOf (t:env) e)
-- /End/
-- Matching
-- /Pat/
data Pat = Any | PArr Ty Pat
matches :: Pat -> Ty -> Bool
matches Any _ = True
matches (PArr t p) (TyArr t1 t2) = t1==t && matches p t2
matches _ _ = False
-- /End/
{- Let the Games begin!
~~~~~~~~~~~~~~~~~~~~ -}
-- Game for matching variables
-- /mkVarGame/
varGame :: (Ty -> Bool) -> Env -> Maybe (Game Nat)
varGame f [] = Nothing
varGame f (t:env) = case varGame f env of
Nothing -> if f t then Just (constGame 0) else Nothing
Just g -> if f t then Just (Split succIso unitGame g)
else Just (g +> Iso pred succ)
-- /End/
progGame :: Game Exp
progGame = expGame [] Any
-- Returns an expression with a type that that matches match
-- Satisfies the "all bits count" property
-- /expGame/
-- (env : Env) -> (p : Pat) ->
-- Game {e | exists t, env |- e : t && matches p t}
expGame :: Env -> Pat -> Game Exp
expGame env p
= case varGame (matches p) env of
Nothing -> appLamG
Just varG -> Split varI varG appLamG
where appLamG = Split appLamI appG (lamG p)
appG = depGame (expGame env Any) $ \e ->
expGame env (PArr (typeOf env e) p)
lamG (PArr t p) = prodGame (constGame t) $
expGame (t:env) p
lamG Any = depGame tyGame $ \t ->
expGame (t:env) Any
varI = Iso ask bld where ask (Var x) = Left x
ask e = Right e
bld (Left x) = Var x
bld (Right e) = e
appLamI = Iso ask bld
where ask (App e1 e2) = Left (e2,e1)
ask (Lam t e) = Right (t,e)
bld (Left (e2,e1)) = App e1 e2
bld (Right (t,e)) = Lam t e
-- /End/
-- Returns a game for terms in a *given* environment and *given* type.
-- /expGameCheck/
-- (env:Env) -> (t:Ty) -> Game {e | env |- e : t}
expGameCheck :: Env -> Ty -> Game Exp
expGameCheck env t
= case varGame (== t) env of
Nothing -> appLamG t
Just varG -> Split varI varG (appLamG t)
where appLamG TyNat
= appG +> Iso (\(App e1 e2)->(e2,e1))
(\(e2,e1)->App e1 e2)
appLamG (TyArr t1 t2)
= let ask (App e1 e2) = Left (e2,e1)
ask (Lam t e) = Right e
bld (Left (e2,e1)) = App e1 e2
bld (Right e) = Lam t1 e
in Split (Iso ask bld) appG (lamG t1 t2)
appG = depGame (expGame env Any) $ \e ->
expGameCheck env (TyArr (typeOf env e) t)
lamG t1 t2 = expGameCheck (t1:env) t2
-- /End/
-- -- A strong model for terms (will be strong only if there are infinite inhabitants)
-- -- [Satisfies the all bits count property]
-- /expGameCheckProper/
expGameCheckProper env t
= filterGame_inf (\_ -> True) (expGameCheck env t)
-- /End/
-- /allTerms/
all01 = [1] : map (0:) all01
-- Games for the empty environment and type Nat -> Nat
allNat2Nat = map (fst . dec game) all01
where game = expGameCheckProper [] (TyArr TyNat TyNat)
-- /End/
-- decRandomTm i = run decClosedTm (mkRandom i)
listsOfLength :: Int -> [[Bit]]
listsOfLength 0 = [[]]
listsOfLength (n+1) = map (0:) (listsOfLength n) ++ map (1:) (listsOfLength n)
allLists n = listsOfLength n ++ allLists (n+1)
enumerateTms (x:l) =
case decOpt (expGame [] Any) x of
Just (e,[]) -> e : enumerateTms l
_ -> enumerateTms l
allTms = enumerateTms (allLists 0)
ex = Lam TyNat (Lam TyNat (Var 1))