Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
data Expr = Num Int
| Expr `Plus` Expr
| Expr `Minus` Expr
| Expr `Mul` Expr
| Expr `Div` Expr
| Var String
| Count
deriving Show
exp1 = (Num 1) `Plus` (Num 2)
exp2 = (Num 4) `Minus` (Num 3)
exp3 = exp1 `Mul` (Num 5)
newtype IdM a = I a
deriving Show
runIdM (I x) = x
instance Monad IdM where
I x >>= k = k x
return x = I x
evalI :: Expr -> IdM Int
evalI (Num i) = return i
evalI (e1 `Plus` e2) = do v1 <- evalI e1
v2 <- evalI e2
return (v1+v2)
evalI (e1 `Minus` e2) = do v1 <- evalI e1
v2 <- evalI e2
return (v1+v2)
evalI (e1 `Mul` e2) = do v1 <- evalI e1
v2 <- evalI e2
return (v1+v2)
evalI (e1 `Div` e2) = do v1 <- evalI e1
v2 <- evalI e2
return (v1 `div` v2)
runMaybe (Just x) = x
evalM :: Expr -> Maybe Int
evalM (Num i) = return i
evalM (e1 `Plus` e2) = do v1 <- evalM e1
v2 <- evalM e2
return (v1+v2)
evalM (e1 `Minus` e2) = do v1 <- evalM e1
v2 <- evalM e2
return (v1+v2)
evalM (e1 `Mul` e2) = do v1 <- evalM e1
v2 <- evalM e2
return (v1+v2)
evalM (e1 `Div` e2) = do v1 <- evalM e1
v2 <- evalM e2
if v2 == 0
then fail "Division by zero"
else return (v1 `div` v2)
type Env = [(String,Int)]
lookupE :: String -> Env -> Maybe Int
lookupE x = \env -> case [v | (y,v) <- env, y == x] of
[] -> fail ("Free variable: " ++ x)
v:_ -> return v
evalE :: Expr -> Env -> Maybe Int
evalE (Num i) = \env -> return i
evalE (e1 `Plus` e2) = \env -> do v1 <- evalE e1 env
v2 <- evalE e2 env
return (v1+v2)
evalE (e1 `Minus` e2) = \env -> do v1 <- evalE e1 env
v2 <- evalE e2 env
return (v1+v2)
evalE (e1 `Mul` e2) = \env -> do v1 <- evalE e1 env
v2 <- evalE e2 env
return (v1+v2)
evalE (e1 `Div` e2) = \env -> do v1 <- evalE e1 env
v2 <- evalE e2 env
if v2 == 0
then fail "Division by zero"
else return (v1 `div` v2)
evalE (Var x) = \env -> lookupE x env
newtype Reader r a = R (r -> Maybe a)
bindR :: Reader r a -> (a -> Reader r b) -> Reader r b
(R ma) `bindR` f = R (\ r -> ma r >>= \ a ->
case f a of R f' -> f' r)
runReader :: Reader r a -> r -> Maybe a
runReader (R r) e = r e
lookupR :: String -> Reader Env Int
lookupR x = R $ \env -> case [v | (y,v) <- env, y == x] of
[] -> fail ("Free variable: " ++ x)
v:_ -> return v
instance Monad (Reader r) where
return a = R (\ _ -> return a)
(>>=) = bindR
fail s = R (\ _ -> fail s)
evalR :: Expr -> Reader Env Int
evalR (Num i) = return i
evalR (e1 `Plus` e2) = do v1 <- evalR e1
v2 <- evalR e2
return (v1+v2)
evalR (e1 `Minus` e2) = do v1 <- evalR e1
v2 <- evalR e2
return (v1+v2)
evalR (e1 `Mul` e2) = do v1 <- evalR e1
v2 <- evalR e2
return (v1+v2)
evalR (e1 `Div` e2) = do v1 <- evalR e1
v2 <- evalR e2
if v2 == 0
then fail "Division by zero"
else return (v1 `div` v2)
evalR (Var x) = lookupR x
newtype IntSt a = ISt (Int -> (a,Int))
instance Monad IntSt where
return x = ISt (\s -> (x,s))
k >>= f = ISt (\s -> let ISt k' = k
(x,s') = k' s
ISt f' = f x
in f' s')
getInt :: IntSt Int
getInt = ISt (\s -> (s,s))
putInt :: Int -> IntSt ()
putInt x = ISt (\s -> ((),x))
runIntSt :: IntSt a -> Int -> a
runIntSt f s = let ISt f' = f
in fst (f' s)
inc :: IntSt Int
inc = getInt >>= \i ->
putInt (i+1) >>
return i
evalS :: Expr -> IntSt Int
evalS (Num i) = return i
evalS (e1 `Plus` e2) = do v1 <- evalS e1
v2 <- evalS e2
return (v1+v2)
evalS (e1 `Minus` e2) = do v1 <- evalS e1
v2 <- evalS e2
return (v1+v2)
evalS (e1 `Mul` e2) = do v1 <- evalS e1
v2 <- evalS e2
return (v1+v2)
evalS (e1 `Div` e2) = do v1 <- evalS e1
v2 <- evalS e2
return (v1 `div` v2)
evalS Count = inc