|
| 1 | +{-# LANGUAGE DeriveDataTypeable #-} |
| 2 | +module ContractTypes |
| 3 | + where |
| 4 | + |
| 5 | +-- to define the exception |
| 6 | +import Control.Exception |
| 7 | +import Data.Typeable |
| 8 | + |
| 9 | +data Currency = EUR | DKK | SEK | USD | GBP | JPY |
| 10 | +-- good enough with only FX derivatives. Otherwise we could add this: |
| 11 | +-- "... | Stock String | Equity String" |
| 12 | + |
| 13 | +ppCur EUR = "EUR" |
| 14 | +ppCur DKK = "DKK" |
| 15 | +ppCur SEK = "SEK" |
| 16 | +ppCur USD = "USD" |
| 17 | +ppCur GBP = "GBP" |
| 18 | +ppCur JPY = "JPY" |
| 19 | + |
| 20 | +-- submodule expression starts here |
| 21 | +type Var = String |
| 22 | + |
| 23 | +type BoolE = Expr Bool |
| 24 | +type IntE = Expr Int |
| 25 | +type RealE = Expr Double |
| 26 | + |
| 27 | +var :: Var -> Expr a |
| 28 | + |
| 29 | +type BinOpT a = Expr a -> Expr a -> Expr a |
| 30 | + |
| 31 | +(!+!) :: Num a => BinOpT a |
| 32 | +(!-!) :: Num a => BinOpT a |
| 33 | +(!*!) :: Num a => BinOpT a |
| 34 | +(!<!) :: Expr a -> Expr a -> Expr Bool |
| 35 | +(!=!) :: Expr a -> Expr a -> Expr Bool |
| 36 | +(!|!) :: BinOpT Bool |
| 37 | +obs :: (String, Int) -> Expr a |
| 38 | +i :: Int -> IntE |
| 39 | +r :: Double -> RealE |
| 40 | +b :: Bool -> BoolE |
| 41 | + |
| 42 | +data EvalExc = Eval String deriving (Read,Show,Typeable) |
| 43 | +instance Exception EvalExc |
| 44 | + |
| 45 | +type Env = (String, Int) -> RealE -- nicer if it was Expr a |
| 46 | + |
| 47 | +evalR :: Env -> RealE -> Double |
| 48 | +evalI :: Env -> IntE -> Int |
| 49 | +evalB :: Env -> BoolE -> Bool |
| 50 | + |
| 51 | +-- general: |
| 52 | +evalX :: Env -> Expr a -> a |
| 53 | +evalX = undefined |
| 54 | +-- all these evaluators assume that the expr _can_ be evaluated, |
| 55 | +-- i.e. all required fixings are known |
| 56 | + |
| 57 | +data Expr0 = I Int | R Double | B Bool | V Var |
| 58 | + | BinOp String Expr0 Expr0 | UnOp String Expr0 | Obs (String,Int) |
| 59 | +type Expr a = Expr0 |
| 60 | + |
| 61 | +{- should be using a GADT instead |
| 62 | +data ExprG a where |
| 63 | + I :: Int -> ExprG Int |
| 64 | + R :: Double -> ExprG Double |
| 65 | + B :: Bool -> ExprG Bool |
| 66 | + V :: Var -> ExprG a |
| 67 | + ... should this split up the operators according to their phantom types? |
| 68 | +-} |
| 69 | + |
| 70 | +-- infix !+! !-! !*! !<! !=! !|! |
| 71 | +x !+! y = BinOp "+" x y |
| 72 | +x !-! y = BinOp "-" x y |
| 73 | +x !*! y = BinOp "*" x y |
| 74 | +x !<! y = BinOp "<" x y |
| 75 | +x !=! y = BinOp "=" x y |
| 76 | +x !|! y = BinOp "|" x y |
| 77 | + |
| 78 | +obs = Obs |
| 79 | +var = V |
| 80 | +i = I |
| 81 | +r = R |
| 82 | +b = B |
| 83 | + |
| 84 | +binopII opr i1 i2 = |
| 85 | + case opr of |
| 86 | + "+" -> I (i1+i2) |
| 87 | + "-" -> I (i1-i2) |
| 88 | + "*" -> I (i1*i2) |
| 89 | + "<" -> B (i1<i2) |
| 90 | + "=" -> B (i1==i2) |
| 91 | + _ -> error ("binopII: operator not supported: " ++ opr) |
| 92 | +binopRR opr r1 r2 = |
| 93 | + case opr of |
| 94 | + "+" -> R (r1+r2) |
| 95 | + "-" -> R (r1-r2) |
| 96 | + "*" -> R (r1*r2) |
| 97 | + "<" -> B (r1<r2) |
| 98 | + "=" -> B (r1==r2) |
| 99 | + _ -> error ("binopRR: operator not supported: " ++ opr) |
| 100 | +binopBB opr b1 b2 = |
| 101 | + case opr of |
| 102 | + "=" -> B (b1==b2) |
| 103 | + _ -> error ("binopBB: operator not supported: " ++ opr) |
| 104 | + |
| 105 | +eval env e = |
| 106 | + case e of |
| 107 | + V s -> error ("variable " ++ s) |
| 108 | + I _ -> e |
| 109 | + R _ -> e |
| 110 | + B _ -> e |
| 111 | + Obs u -> case env u of |
| 112 | + Obs u' -> if u == u' then throw $ Eval "unresolved observable" |
| 113 | + else eval env (Obs u') |
| 114 | + e' -> eval env e' |
| 115 | + BinOp opr e1 e2 -> |
| 116 | + case (eval env e1, eval env e2) of |
| 117 | + (I i1, I i2) -> binopII opr i1 i2 |
| 118 | + (R r1, R r2) -> binopRR opr r1 r2 |
| 119 | + (B b1, B b2) -> binopBB opr b1 b2 |
| 120 | + _ -> error "eval.BinOp: difference in argument types" |
| 121 | + UnOp "not" e1 -> |
| 122 | + case eval env e1 of |
| 123 | + B b -> B (not b) |
| 124 | + _ -> error "eval.UnOp.not - wrong argument type" |
| 125 | + UnOp opr _ -> error ("eval.UnOp: unsupported operator: " ++ opr) |
| 126 | + |
| 127 | +evalR env e = case eval env e of |
| 128 | + R r -> r |
| 129 | + _ -> error "evalR: expecting real" |
| 130 | +evalI env e = case eval env e of |
| 131 | + I i -> i |
| 132 | + _ -> error "evalI: expecting real" |
| 133 | +evalB env e = case eval env e of |
| 134 | + B b -> b |
| 135 | + _ -> error "evalB: expecting real" |
| 136 | + |
| 137 | +type Party = String |
| 138 | + |
| 139 | +data Contract = |
| 140 | + TransfOne Currency Party Party |
| 141 | + | Scale RealE Contract |
| 142 | + | Transl IntE Contract |
| 143 | + | All [Contract] |
| 144 | + | If BoolE Contract Contract |
| 145 | + | Iter IntE (Var -> Contract) -- how to use it? |
| 146 | + | CheckWithin BoolE IntE Contract Contract |
| 147 | + -- if cond::BoolE becomes true within time::IntE then contract1 in effect. |
| 148 | + -- otherwise (time expired, always false) contract2 in effect |
0 commit comments