haskell - Haskell - 作为函数的输入
问题描述
我正在为一小步 WHILE 解释器查看此代码,并且我正在尝试了解如何运行它。具体来说,我对 State 类型感到困惑。它似乎是一种函数 - 这是否意味着必须在某处定义 State = Var->Val 类型的函数,并且该函数需要传递给需要它的函数?
同时,我看到状态应该可以通过变量赋值来修改。如果 upd 函数只传递给 Var->Val 类型的函数,它是如何工作的?
谢谢你的帮助!我似乎在教程或 stackoverflow 上找不到任何关于此的内容。
type Var = Integer
type Val = Integer
type State = Var -> Val
--takes a var, returns a val. Here, we use an integer to describe a
-- variable as opposed to a string.
lkp :: Var -> State -> Val
lkp x s = s x
upd :: Var -> Val -> State -> State
upd x v s = \y -> if x == y then v else s y
data AExp = N Integer | V Var
| AExp :+ AExp | AExp :- AExp | AExp :* AExp
deriving (Show)
aexp :: AExp -> State -> Integer
aexp (N z) _ = z
aexp (V x) s = lkp x s
aexp (a0 :+ a1) s = aexp a0 s + aexp a1 s
aexp (a0 :- a1) s = aexp a0 s - aexp a1 s
aexp (a0 :* a1) s = aexp a0 s * aexp a1 s
data BExp = TT | FF | AExp :== AExp | AExp :<= AExp
| Not BExp | BExp :&& BExp | BExp :|| BExp
deriving (Show)
bexp :: BExp -> State -> Bool
bexp TT _ = True
bexp FF _ = False
bexp (a0 :== a1) s = aexp a0 s == aexp a1 s
bexp (a0 :<= a1) s = aexp a0 s <= aexp a1 s
bexp (Not b) s = not (bexp b s)
bexp (a0 :&& a1) s = bexp a0 s && bexp a1 s
bexp (a0 :|| a1) s = bexp a0 s || bexp a1 s
data Stmt = Skip | Stmt :\ Stmt | Var := AExp
| If BExp Stmt Stmt | While BExp Stmt
data Trace = Nil State | Delay State Trace
--reduces the statement by one step.
red :: Stmt -> State -> Maybe (Stmt, State)
red Skip s = Nothing
red (x := a) s = Just (Skip, upd x v s) where v = aexp a s
red (stmt0 :\ stmt1) s =
case red stmt0 s of
Just (stmt0', s') -> Just (stmt0' :\ stmt1, s')
Nothing -> red stmt1 s
red (If b stmt0 stmt1) s =
if bexp b s then
Just (stmt0, s)
else Just (stmt1, s)
red (While b stmt0) s =
if bexp b s then
Just (stmt0 :\ While b stmt0, s)
else Just (Skip, s)
norm :: Stmt -> State -> Trace
norm stmt s =
case red stmt s of
Nothing -> Nil s
Just (stmt', s') -> Delay s (norm stmt' s')
解决方案
您可以将State
类型视为可以查找变量的环境。您可以从一个“空”环境开始,如下所示:
emptyState v = error ("variable " ++ show v ++ " is unknown")
据我所知,每次解释器看到一个
var := value
构造。也就是说,之后
V 23 := 42
后续语句中使用的状态函数将如下所示:
state1 v = if v == 23 then 42 else emptyState v
有趣的是,emptyState
函数的设置决定了解释语言的重要语义属性。emptyState
例如,上面禁止未定义的变量。但也有可能想出一个变体,将所有未定义的变量视为 0、1 或 42。