[5] | 1 | {-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, |
---|
| 2 | IncoherentInstances, RankNTypes, ScopedTypeVariables, |
---|
| 3 | FlexibleContexts,UndecidableInstances #-} |
---|
[17] | 4 | -- |
---|
| 5 | -- Copyright (C) 2012 Attila Gobi - http://kp.elte.hu/sizechecking |
---|
| 6 | -- |
---|
[5] | 7 | |
---|
| 8 | module SizedExp where |
---|
| 9 | |
---|
[17] | 10 | import Lambda as L |
---|
| 11 | import Constraints |
---|
[5] | 12 | import Data.Supply |
---|
[12] | 13 | import Control.Arrow |
---|
| 14 | import Control.Monad |
---|
[5] | 15 | |
---|
| 16 | class TS b => (Unify se a b) where |
---|
[17] | 17 | unify :: (forall a b c. (TS c, Unify se a b) => c -> (Size se c -> a) -> (Size se (c -> b), d)) -> |
---|
| 18 | (b -> Size se b -> (Size se b, d)) -> |
---|
[5] | 19 | a -> (Size se b, d) |
---|
| 20 | |
---|
| 21 | instance (SizedExp se, Unify se a b, se~se1, c1~c2, TS c2) => Unify se (Size se1 c1->a) (c2->b) where |
---|
[12] | 22 | unify f g = f undefined |
---|
[5] | 23 | |
---|
| 24 | instance (SizedExp se, se~se1, c1~c2, TS c2) => Unify se (Size se1 c1) c2 where |
---|
[12] | 25 | unify f g = g undefined |
---|
[5] | 26 | |
---|
| 27 | class SizedExp (se :: * -> *) where |
---|
| 28 | data Size se :: * -> * |
---|
| 29 | true :: Size se x |
---|
| 30 | known :: L -> Size se x |
---|
| 31 | match :: Size se [l] -> Size se r -> (Size se l -> Size se [l] -> Size se r) -> Size se r |
---|
| 32 | bind :: (Unify se a b) => L.L -> a -> Size se b |
---|
| 33 | app :: Size se (a->b) -> Size se a -> Size se b |
---|
| 34 | iff :: Bool -> Size se a -> Size se a -> Size se a |
---|
| 35 | num :: Integer -> Size se Int |
---|
| 36 | |
---|
| 37 | instance Show (Size se a) where |
---|
| 38 | show (==) = error "no show on Size!" |
---|
| 39 | instance Eq (Size se a) where |
---|
| 40 | (==) = undefined |
---|
| 41 | instance (SizedExp se) => Num (Size se Int) where |
---|
| 42 | fromInteger = num |
---|
| 43 | x + y = num 0 |
---|
| 44 | x * y = num 0 |
---|
| 45 | abs = undefined |
---|
| 46 | signum = undefined |
---|
| 47 | instance (SizedExp se) => Ord(Size se Int) where |
---|
| 48 | |
---|
| 49 | {- |
---|
| 50 | - Implementation of constraints |
---|
| 51 | -} |
---|
| 52 | sizeof :: Size Q a -> IO [SExp] |
---|
| 53 | sizeof (QSynt s) = s |
---|
| 54 | sizeof (QProvable l _) = return [([], l)] |
---|
| 55 | |
---|
| 56 | fresh :: TypeKind -> Supply Int -> L |
---|
| 57 | fresh sig var = fresh' sig [] var |
---|
[17] | 58 | where |
---|
[5] | 59 | fresh' U _ _ = Unsized |
---|
| 60 | fresh' V l var = appall (supplyValue var) l |
---|
| 61 | fresh' (F _ b) l var = Abs i $ fresh' b (Var i:l) v2 |
---|
| 62 | where |
---|
| 63 | (v1,v2) = split2 var |
---|
| 64 | i = supplyValue v1 |
---|
| 65 | fresh' (L a) l var = List (appall i l) (Abs j $ fresh' a (Var j:l) v3) |
---|
| 66 | where |
---|
| 67 | (v1,v2,v3) = split3 var |
---|
| 68 | i = supplyValue v1 |
---|
| 69 | j = supplyValue v2 |
---|
| 70 | |
---|
| 71 | |
---|
| 72 | freshvars2 :: (TS b, Unify Q (Size Q a) a) => Supply Int -> b -> Size Q a -> (Size Q a, L -> L) |
---|
| 73 | freshvars2 supply q exp = (exp , id) |
---|
| 74 | |
---|
| 75 | freshvars :: (TS c, Unify Q a b) => Supply Int -> c -> (Size Q c -> a) -> (Size Q (c -> b), L -> L) |
---|
[17] | 76 | freshvars supply q = freshvars' (unify (freshvars s1) (freshvars2 s2)) |
---|
| 77 | where |
---|
[5] | 78 | (s1, s2, s3) = split3 supply |
---|
| 79 | freshvars' :: (Unify Q a b) => (a -> (Size Q b, L -> L)) -> (Size Q c -> a) -> (Size Q (c -> b), L -> L) |
---|
[12] | 80 | freshvars' u exp = (QSynt $ sizeof x, \l -> f $ App l fv) |
---|
[5] | 81 | where |
---|
[17] | 82 | (x, f) = u $ exp $ QSynt $ do |
---|
[5] | 83 | return [([], fv)] |
---|
| 84 | fv = fresh (tk q) s3 |
---|
| 85 | |
---|
| 86 | addConstraint :: Constraint -> [SExp] -> [SExp] |
---|
[12] | 87 | addConstraint nc = map (first ((:) nc)) |
---|
[5] | 88 | |
---|
| 89 | concatMapM :: (a -> IO [b]) -> [a] -> IO [b] |
---|
[12] | 90 | concatMapM f l = liftM concat $ mapM f l |
---|
[14] | 91 | |
---|
[5] | 92 | type SExp = ([Constraint], L) |
---|
| 93 | newtype Q a = Q { unQ :: () } |
---|
| 94 | instance SizedExp Q where |
---|
[14] | 95 | data Size Q a = QSynt (IO [SExp]) | QProvable L (Supply Int -> IO [Condition]) |
---|
[5] | 96 | known l = QSynt $return [([], l)] |
---|
| 97 | true = QSynt $ return [] |
---|
| 98 | match l nil cons = let |
---|
| 99 | match1 (cond, ltype) = do |
---|
| 100 | x <- sizeof l |
---|
| 101 | let lt = rall$ App (AAbs 18 5 $ Var 18) ltype |
---|
| 102 | nils <- sizeof nil |
---|
| 103 | let nilc = foldr addConstraint nils $ Zero lt:cond |
---|
| 104 | let tx = rall $ App (AAbs 18 5 $ App (Var 5) (Op (Var 18) '-' (Num 1))) ltype |
---|
| 105 | let txs = rall $App (AAbs 18 5 $ List (Op (Var 18) '-' (Num 1)) (Var 5)) ltype |
---|
| 106 | conss <- sizeof $ cons (QSynt$return [([], tx)]) (QSynt$return [([], txs)]) |
---|
| 107 | let consc = foldr addConstraint conss $ lt `GEC` Num 1:cond |
---|
| 108 | return $ nilc ++ consc |
---|
[17] | 109 | in QSynt $ sizeof l >>= concatMapM match1 |
---|
[5] | 110 | |
---|
[17] | 111 | iff _ l1 l2 = QSynt $ do |
---|
[5] | 112 | ll1 <- sizeof l1 |
---|
| 113 | ll2 <- sizeof l2 |
---|
| 114 | return $ ll1 ++ ll2 |
---|
| 115 | |
---|
| 116 | app l1 l2 = QSynt $ do |
---|
| 117 | ll1 <- sizeof l1 |
---|
| 118 | ll2 <- sizeof l2 |
---|
| 119 | return [ (c1 ++ c2, App e1 e2) | (c1,e1) <- ll1, (c2,e2) <- ll2] |
---|
| 120 | |
---|
| 121 | bind l exp = z $ \supply -> let (s1,s2) = split2 supply in unify (freshvars s1) (freshvars2 s2) exp |
---|
| 122 | where |
---|
| 123 | z :: (Supply Int -> (Size Q c, L -> L)) -> Size Q c |
---|
| 124 | z x = QProvable l $ \supply -> let |
---|
| 125 | (sexp, f) = x supply |
---|
| 126 | ll = rall $ f l |
---|
| 127 | rr (Zero a) = Zero $ rall a |
---|
| 128 | rr (GEC a b) = rall a `GEC` rall b |
---|
| 129 | rr (LTC a b) = rall a `LTC` rall b |
---|
[17] | 130 | in do |
---|
| 131 | l3 <- sizeof sexp |
---|
[5] | 132 | return $ map (\(c,l2) -> Condition (map rr c) ll (rall l2)) l3 |
---|
| 133 | |
---|
| 134 | num n = QSynt $return [([], Unsized)] |
---|
| 135 | |
---|
| 136 | instance Num (Size Q Int) where |
---|
| 137 | (+) = undefined |
---|
| 138 | (*) = undefined |
---|
| 139 | abs = undefined |
---|
| 140 | signum = undefined |
---|
| 141 | fromInteger = num |
---|
| 142 | |
---|
[14] | 143 | conditions :: Size Q b -> IO () |
---|
| 144 | conditions (QProvable l x) = do |
---|
| 145 | (s1,s2,s3) <- liftM split3 $ newSupply 30 (+1) |
---|
| 146 | c <- x s1 |
---|
| 147 | print c |
---|
| 148 | |
---|
[12] | 149 | prove :: Size Q b -> IO Bool |
---|
[5] | 150 | prove (QProvable l x) = do |
---|
[12] | 151 | (s1,s2,s3) <- liftM split3 $ newSupply 30 (+1) |
---|
[5] | 152 | c <- x s1 |
---|
| 153 | putStrLn "" |
---|
| 154 | putStrLn "------------" |
---|
| 155 | putStrLn "Conditions: " |
---|
| 156 | print c |
---|
| 157 | putStrLn "" |
---|
| 158 | putStrLn "------------" |
---|
| 159 | putStrLn "Equations: " |
---|
| 160 | x <- checkCond s2 c |
---|
| 161 | print x |
---|
| 162 | putStrLn "" |
---|
| 163 | putStrLn "------------" |
---|
| 164 | putStrLn "Solving: " |
---|
| 165 | y <- solve x s3 |
---|
| 166 | putStrLn "" |
---|
| 167 | if null y then do |
---|
| 168 | putStrLn "QED" |
---|
| 169 | return True |
---|
[11] | 170 | else do |
---|
[5] | 171 | putStrLn "------------" |
---|
| 172 | putStrLn "Cannot prove: " |
---|
| 173 | print y |
---|
| 174 | return False |
---|