Type signatures
[darcs-mirror-polyfix.git] / SimpleFT.hs
1 {-# LANGUAGE PatternGuards, FlexibleContexts  #-}
2
3 module SimpleFT where
4
5 import ParseType
6 import Expr
7 import Control.Monad.Reader
8 import Data.List
9
10 test :: String -> IO ()
11 test = putStrLn . show . freeTheorem . parseType
12
13 freeTheorem :: Typ -> BoolExpr
14 freeTheorem t = flip runReader freeVars $ 
15                         freeTheorem' (typedLeft  (Var "f") (unquantify t))
16                                      (typedRight (Var "f") (unquantify t))
17                                      t
18 freeVars :: [String]
19 freeVars = map (:"") (delete 'f' ['a'..])
20
21
22 freeTheorem' :: TypedExpr -> TypedExpr -> Typ -> Reader [String] BoolExpr
23
24 freeTheorem' e1 e2 Int = return $
25         equal e1 e2
26
27 freeTheorem' e1 e2 (TVar (TypVar i)) = return $
28         let tv = TypedExpr (Var ("g"++show i))
29                            (Arrow (TVar (TypInst i False)) (TVar (TypInst i True)))
30         in equal (app tv e1) e2
31
32 freeTheorem' e1 e2 (Arrow t1 t2) | isTuple t1 = do
33         -- Create patterns for (possily nested) tuples and only give
34         -- the inner variables names
35         fillTuplevars False t1 $ \vars1 tve1  -> 
36                 fillTuplevars True t1 $ \vars2 tve2  ->  do
37                         cond  <- freeTheorem' (tve1) (tve2) t1
38                         concl <- freeTheorem' (app e1 tve1) (app e2 tve2) t2
39                         return $ condition (vars1 ++ vars2) cond concl
40
41         -- No tuple on the left hand side:
42                                  | otherwise  = getSideVars t1 $ \(v1,v2) -> do
43         cond  <- freeTheorem'  v1  v2 t1
44         concl <- freeTheorem' (app e1  v1) (app e2  v2) t2
45         return $ condition [ v1, v2 ] cond concl
46
47 freeTheorem' e1 e2 (List t) = getSideVars t $ \(v1,v2) -> do
48         mapRel <- freeTheorem' v1 v2 t
49         return $ allZipWith v1 v2 mapRel e1 e2
50
51 {-
52 freeTheorem' e1 e2 (TPair t1 t2) = getVars 4 $ \[x1,x2,y1,y2] -> do
53         concl1 <- freeTheorem' (Var x1) (Var y1) t1
54         concl2 <- freeTheorem' (Var x2) (Var y2) t2
55         return $ Condition x1 y1 t1 BETrue $
56                  Condition x2 y2 t2 (
57                         And (Equal e2 (Pair (Var y1) (Var y2)))
58                             (Equal e1 (Pair (Var x1) (Var x2)))) $
59                         And concl1 concl2
60 -}
61
62 freeTheorem' e1 e2 (TPair t1 t2) 
63         | (Pair   x1  x2) <- unTypeExpr e1
64         , (Pair   y1  y2) <- unTypeExpr e2
65            = do concl1 <- freeTheorem' 
66                         (TypedExpr x1 tx1)
67                         (TypedExpr y1 ty1)
68                         t1
69                 concl2 <- freeTheorem'
70                         (TypedExpr x2 tx2)
71                         (TypedExpr y2 ty2)
72                         t2
73                 return $ aand concl1 concl2
74         | otherwise
75            = getVars 4 $ \[x1',x2',y1',y2'] -> do
76                 let x1 = TypedExpr (Var x1') tx1
77                     x2 = TypedExpr (Var x2') tx2
78                     y1 = TypedExpr (Var y1') ty1
79                     y2 = TypedExpr (Var y2') ty2
80                 concl1 <- freeTheorem' x1 y1 t1
81                 concl2 <- freeTheorem' x2 y2 t2
82                 return $ unpackPair x1 x2 e1 $
83                                 unpackPair y1 y2 e2  $
84                                         aand concl1 concl2
85  where (TPair tx1 tx2) = typeOf e1
86        (TPair ty1 ty2) = typeOf e2
87
88 freeTheorem' e1 e2 (AllStar (TypVar i) t) = TypeVarInst i `fmap` freeTheorem' e1 e2 t
89 freeTheorem' e1 e2 (All     (TypVar i) t) = TypeVarInst i `fmap` freeTheorem' e1 e2 t
90
91 getVars :: (MonadReader [String] m) => Int -> ([String] -> m a) -> m a
92 getVars n a = asks (take n) >>= local (drop n) . a 
93
94 getSideVars :: (MonadReader [String] m) => Typ -> ((TypedExpr,TypedExpr) -> m a) -> m a
95 getSideVars t a = getVars 2 $ \[v1,v2] -> a (typedLeft (Var v1) t, typedRight (Var v2) t)
96
97 -- Given a (nested) tuple type, generates vars for each place
98 -- and returns them, once as list and onces as one (nested) tuple
99 fillTuplevars :: (MonadReader [String] m) =>
100                  Bool -> Typ -> ([TypedExpr] -> TypedExpr -> m a) -> m a
101 fillTuplevars rightSide t@(TPair t1 t2) a = do
102         fillTuplevars rightSide t1 $ \vars1 ve1  ->
103                 fillTuplevars rightSide t2 $ \vars2 ve2 ->
104                         let untypedPair  = Pair (unTypeExpr ve1) (unTypeExpr ve2)
105                             tpair = TypedExpr untypedPair (instType rightSide t)
106                         in a (vars1 ++ vars2) tpair
107 fillTuplevars rightSide t a = getVars 1 $ \[s] ->
108                         let tvar = TypedExpr (Var s) (instType rightSide t)
109                         in a [tvar] tvar