[5] | 1 | {-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances, |
---|
| 2 | IncoherentInstances, RankNTypes, ScopedTypeVariables, |
---|
| 3 | FlexibleContexts,UndecidableInstances #-} |
---|
| 4 | |
---|
| 5 | module SizedExp where |
---|
| 6 | -- ( |
---|
| 7 | -- SizedExp(..), ($), unQ, prove |
---|
| 8 | -- ) where |
---|
| 9 | |
---|
| 10 | import Lambda as L |
---|
| 11 | import Constraints |
---|
| 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 | 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)) -> |
---|
| 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 |
---|
| 58 | where |
---|
| 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) |
---|
| 76 | freshvars supply q = freshvars' (unify (freshvars s1) (freshvars2 s2)) |
---|
| 77 | where |
---|
| 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 |
---|
| 82 | (x, f) = u $ exp $ QSynt $ do |
---|
[14] | 83 | -- putStrLn $ "[Bind] var="++ show fv ++" of type "++ show (tk q) |
---|
[5] | 84 | return [([], fv)] |
---|
| 85 | fv = fresh (tk q) s3 |
---|
| 86 | |
---|
| 87 | addConstraint :: Constraint -> [SExp] -> [SExp] |
---|
[12] | 88 | addConstraint nc = map (first ((:) nc)) |
---|
[5] | 89 | |
---|
| 90 | concatMapM :: (a -> IO [b]) -> [a] -> IO [b] |
---|
[12] | 91 | concatMapM f l = liftM concat $ mapM f l |
---|
[14] | 92 | |
---|
[5] | 93 | type SExp = ([Constraint], L) |
---|
| 94 | newtype Q a = Q { unQ :: () } |
---|
| 95 | instance SizedExp Q where |
---|
[14] | 96 | data Size Q a = QSynt (IO [SExp]) | QProvable L (Supply Int -> IO [Condition]) |
---|
[5] | 97 | known l = QSynt $return [([], l)] |
---|
| 98 | true = QSynt $ return [] |
---|
| 99 | match l nil cons = let |
---|
| 100 | match1 (cond, ltype) = do |
---|
| 101 | x <- sizeof l |
---|
[14] | 102 | -- putStrLn $ "ORIGINAL is " ++ show x |
---|
| 103 | -- putStrLn $ "[MATCH] ==> " ++ show ltype |
---|
[5] | 104 | let lt = rall$ App (AAbs 18 5 $ Var 18) ltype |
---|
[14] | 105 | -- putStrLn $ " --- NIL ---" ++ show lt |
---|
[5] | 106 | nils <- sizeof nil |
---|
[14] | 107 | -- print nils |
---|
[5] | 108 | let nilc = foldr addConstraint nils $ Zero lt:cond |
---|
| 109 | let tx = rall $ App (AAbs 18 5 $ App (Var 5) (Op (Var 18) '-' (Num 1))) ltype |
---|
| 110 | let txs = rall $App (AAbs 18 5 $ List (Op (Var 18) '-' (Num 1)) (Var 5)) ltype |
---|
[14] | 111 | -- putStrLn $ " --- CONS --- "++ show tx ++" <-> "++ show txs |
---|
[5] | 112 | conss <- sizeof $ cons (QSynt$return [([], tx)]) (QSynt$return [([], txs)]) |
---|
[14] | 113 | -- print conss |
---|
[5] | 114 | let consc = foldr addConstraint conss $ lt `GEC` Num 1:cond |
---|
[14] | 115 | -- print "END MATCH" |
---|
| 116 | -- print $ nilc ++ consc |
---|
[5] | 117 | return $ nilc ++ consc |
---|
| 118 | in QSynt $ sizeof l >>= concatMapM match1 |
---|
| 119 | |
---|
| 120 | iff _ l1 l2 = QSynt $ do |
---|
| 121 | ll1 <- sizeof l1 |
---|
| 122 | ll2 <- sizeof l2 |
---|
| 123 | return $ ll1 ++ ll2 |
---|
| 124 | |
---|
| 125 | app l1 l2 = QSynt $ do |
---|
| 126 | ll1 <- sizeof l1 |
---|
| 127 | ll2 <- sizeof l2 |
---|
| 128 | return [ (c1 ++ c2, App e1 e2) | (c1,e1) <- ll1, (c2,e2) <- ll2] |
---|
| 129 | |
---|
| 130 | bind l exp = z $ \supply -> let (s1,s2) = split2 supply in unify (freshvars s1) (freshvars2 s2) exp |
---|
| 131 | where |
---|
| 132 | z :: (Supply Int -> (Size Q c, L -> L)) -> Size Q c |
---|
| 133 | z x = QProvable l $ \supply -> let |
---|
| 134 | (sexp, f) = x supply |
---|
| 135 | ll = rall $ f l |
---|
| 136 | rr (Zero a) = Zero $ rall a |
---|
| 137 | rr (GEC a b) = rall a `GEC` rall b |
---|
| 138 | rr (LTC a b) = rall a `LTC` rall b |
---|
| 139 | in do |
---|
| 140 | l3 <- sizeof sexp |
---|
[14] | 141 | -- print l |
---|
| 142 | -- print ll |
---|
[5] | 143 | return $ map (\(c,l2) -> Condition (map rr c) ll (rall l2)) l3 |
---|
| 144 | |
---|
| 145 | num n = QSynt $return [([], Unsized)] |
---|
| 146 | |
---|
| 147 | instance Num (Size Q Int) where |
---|
| 148 | (+) = undefined |
---|
| 149 | (*) = undefined |
---|
| 150 | abs = undefined |
---|
| 151 | signum = undefined |
---|
| 152 | fromInteger = num |
---|
| 153 | |
---|
[14] | 154 | conditions :: Size Q b -> IO () |
---|
| 155 | conditions (QProvable l x) = do |
---|
| 156 | (s1,s2,s3) <- liftM split3 $ newSupply 30 (+1) |
---|
| 157 | c <- x s1 |
---|
| 158 | print c |
---|
| 159 | |
---|
[12] | 160 | prove :: Size Q b -> IO Bool |
---|
[5] | 161 | prove (QProvable l x) = do |
---|
[12] | 162 | (s1,s2,s3) <- liftM split3 $ newSupply 30 (+1) |
---|
[5] | 163 | c <- x s1 |
---|
| 164 | putStrLn "" |
---|
| 165 | putStrLn "------------" |
---|
| 166 | putStrLn "Conditions: " |
---|
| 167 | print c |
---|
| 168 | putStrLn "" |
---|
| 169 | putStrLn "------------" |
---|
| 170 | putStrLn "Equations: " |
---|
| 171 | x <- checkCond s2 c |
---|
| 172 | print x |
---|
| 173 | putStrLn "" |
---|
| 174 | putStrLn "------------" |
---|
| 175 | putStrLn "Solving: " |
---|
| 176 | y <- solve x s3 |
---|
| 177 | putStrLn "" |
---|
| 178 | if null y then do |
---|
| 179 | putStrLn "QED" |
---|
| 180 | return True |
---|
[11] | 181 | else do |
---|
[5] | 182 | putStrLn "------------" |
---|
| 183 | putStrLn "Cannot prove: " |
---|
| 184 | print y |
---|
| 185 | return False |
---|