Graham Hutton 的 ccc 出了第三版  http://www.cs.nott.ac.uk/~pszgmh/bib.html

照例复制,并运行一番。



module Main where

import Prelude hiding ((>>=), return)

data Expr = Val Int | Add Expr Expr | Throw | Catch Expr Expr | Block Expr | Unblock Expr


data ND a = E | Ret a | ND a  :||:  ND a

g :: Show a =>  ND a -> String
g E = "E"
g (Ret x) = "RET" ++ show x
g  ( x  :||:  y) = (g x) ++ ":||:"  ++ (g y)


return :: a -> ND a
return x = Ret x

reduce :: ND a -> ND a
reduce E = E
reduce (Ret x) = Ret x
reduce  ( x :||:  E) = reduce x
reduce  ( x :||:  y) = (reduce x :||:  y)


(>>=) :: ND a -> (a -> ND b) -> ND b
E >>== f = E
(Ret x) >>= f = f x
( x  :||:  y) >>= f = (x >>= f)  :||: ( y >>= f )



data Code = HALT | PUSH Int Code | ADD Code | THROW | MARK Code Code | UNMARK Code | BLOCK Code | UNBLOCK Code | RESET Code  deriving Show

compile :: Expr -> Code
compile e = comp e HALT

comp :: Expr -> Code -> Code
comp (Val n) c = PUSH n c
comp(Add x y) c=comp x (comp y(ADD c))
comp Throw c = THROW
comp (Catch x y) c = MARK (comp y c) (comp x (UNMARK c))
comp (Block x) c = BLOCK (comp x (RESET c))
comp (Unblock x) c = UNBLOCK (comp x (RESET c))


type Conf = (Stack, Status) 
type Stack = [Elem] 
data Elem = VAL Int | HAN Code | STA Status deriving Show
data Status = B | U deriving Show

exec :: Code -> Conf -> ND Conf 
exec HALT (s, i) =  return (s, i)
exec (PUSH n c) (s, i) = exec c (VAL n:s, i) :||: inter s i
exec (ADD    c) (VAL n : VAL m : s, i) =  exec c (VAL (m + n):s, i) :||: inter s i
exec THROW (s, i)  = fail' s i
exec (MARK c1 c) (s, i) = exec c (HAN c1: s, i) :||: inter s i
exec (UNMARK c)(VAL n : HAN _:s, i) = exec c (VAL n:s,i)
exec (BLOCK c) (s, i) = exec c (STA i : s, B)
exec (UNBLOCK c) (s, i) = exec c (STA i : s, U)
exec (RESET c)(VAL v: STA i:s, _) = exec c (VAL v:s,i) :||:  inter s i
exec _ _ = E

inter :: Stack -> Status -> ND Conf 
inter s B = E
inter s U = fail' s U

fail' :: Stack -> Status -> ND Conf 
fail'(VAL m:s) i = fail' s i
fail' (HAN c:s) i  = exec c (s,i)
fail' (STA i:s) _ = fail' s i 
fail' _ _ = E

main :: IO()
main =
  print (g (reduce (exec (compile ( Unblock (Add (Val 3) (Unblock (Catch Throw (Val 4)))))) ([] , B))))

 

 Haskell 的基础还是很薄弱。体现在两个上问题:

1.  data ND a = ∅ | Ret a | ND a ⊕ ND a  怎么弄。我用的 Haskell for Mac 不行。

2.  (>>=) 去掉之后完全不影响程序。放到这里有什么用?

 

yxy post at 2021-07-10